MCPToolRegistry

org.llm4s.mcp.MCPToolRegistry
See theMCPToolRegistry companion object
class MCPToolRegistry(mcpServers: Seq[MCPServerConfig], localTools: Seq[ToolFunction[_, _]], cacheTTL: Duration, initializeOnStartup: Boolean) extends ToolRegistry, AutoCloseable

ToolRegistry that transparently integrates local tools with tools discovered from one or more MCP servers.

== Tool lookup order == execute tries local tools first. Only when a local tool with the requested name is not found does it query MCP servers. A tool defined locally shadows any MCP tool with the same name.

== Caching == Tool lists fetched from each MCP server are cached for cacheTTL (default 10 minutes). A stale cache entry is refreshed lazily on the next call that requires that server's tools. Call clearCache() or refreshCache() to invalidate proactively.

== Startup initialisation == When initializeOnStartup is true (the default), the registry fetches and caches tools from all configured MCP servers during construction. Set it to false in tests to defer or skip network calls.

== Error handling == If an MCP server cannot be reached or returns an error, the failure is logged and that server's tools are omitted from the response — the registry never throws during tool lookup. A failed client is evicted from the internal client map so the next call attempts a fresh connection.

== Lifecycle == Implements AutoCloseable; call close() (or use Using.resource) to shut down all active MCP transport connections.

Value parameters

cacheTTL

How long a server's tool list is considered fresh; defaults to 10 minutes

initializeOnStartup

When false, MCP connections are deferred until first use

localTools

Tools provided directly without a remote server call

mcpServers

MCP server configurations to query for remote tools

Attributes

Companion
object
Graph
Supertypes
trait AutoCloseable
class ToolRegistry
class Object
trait Matchable
class Any

Members list

Value members

Concrete methods

def clearCache(): Unit

Discards all cached tool lists, forcing a fresh fetch from each MCP server on the next tool lookup.

Discards all cached tool lists, forcing a fresh fetch from each MCP server on the next tool lookup.

Attributes

override def close(): Unit

Attributes

Definition Classes
AutoCloseable
def closeMCPClients(): Unit

Closes all active MCP transport connections and removes them from the internal client map. After this call the registry still holds its local tools; MCP tools will be re-fetched (creating new connections) on the next lookup.

Closes all active MCP transport connections and removes them from the internal client map. After this call the registry still holds its local tools; MCP tools will be re-fetched (creating new connections) on the next lookup.

Attributes

override def execute(request: ToolCallRequest): Either[ToolCallError, Value]

Executes a tool call synchronously, wrapping any thrown exception.

Executes a tool call synchronously, wrapping any thrown exception.

We use Try here (rather than org.llm4s.core.safety.Safety.safely) so that tool execution remains independent of the Safety API and returns Either for direct use by retry/timeout logic. Safety is still used elsewhere in the codebase (e.g. tracing, agent entry points).

Exceptions thrown inside the tool implementation are caught and converted to ToolCallError.ExecutionError with the original throwable preserved (so retry logic can treat e.g. IOException as retryable). Callers always receive a typed Either and never need to guard against unexpected exceptions from tool code.

Tool-returned Left values are propagated unchanged, so callers may receive any ToolCallError subtype that the tool itself produces (not only ExecutionError).

Value parameters

request

The tool name and pre-parsed JSON arguments.

Attributes

Returns

Right(result) on success; Left(ToolCallError.UnknownFunction) when no tool with the given name is registered; Left(ToolCallError.ExecutionError) when the tool throws an exception; or Left(error) with the tool's own ToolCallError when the tool returns a Left directly.

Definition Classes
def getAllTools: Seq[ToolFunction[_, _]]
override def getOpenAITools(strict: Boolean): Arr

Generate OpenAI tool definitions for all tools.

Generate OpenAI tool definitions for all tools.

Value parameters

strict

When true (default), all object properties are treated as required.

Attributes

Returns

A ujson.Arr containing one tool-definition object per registered tool

Definition Classes
def healthCheck(): Map[String, Boolean]

Attempts to initialise a connection to each configured MCP server and reports whether the handshake succeeded.

Attempts to initialise a connection to each configured MCP server and reports whether the handshake succeeded.

Each server is tested by creating (or reusing) its client and calling initialize(). The returned map contains one entry per server, keyed by MCPServerConfig.name, with true meaning the server responded successfully and false meaning initialisation failed (connection refused, timeout, protocol mismatch, etc.).

Attributes

Returns

map from server name to health status; keys match mcpServers.map(_.name)

def refreshCache(): Unit

Eagerly re-fetches tool lists from all configured MCP servers and updates the cache. Useful after deploying changes to MCP server tool definitions. Errors for individual servers are logged but do not prevent other servers from being refreshed.

Eagerly re-fetches tool lists from all configured MCP servers and updates the cache. Useful after deploying changes to MCP server tool definitions. Errors for individual servers are logged but do not prevent other servers from being refreshed.

Attributes

override def tools: Seq[ToolFunction[_, _]]

All tools registered in this registry.

All tools registered in this registry.

Attributes

Definition Classes

Inherited methods

def addToAzureOptions(chatOptions: ChatCompletionsOptions): ChatCompletionsOptions

Adds the tools from this registry to an Azure OpenAI ChatCompletionsOptions

Adds the tools from this registry to an Azure OpenAI ChatCompletionsOptions

Value parameters

chatOptions

The chat options to add the tools to

Attributes

Returns

The updated chat options

Inherited from:
ToolRegistry
def execute(request: ToolCallRequest, config: ToolExecutionConfig)(implicit ec: ExecutionContext): Either[ToolCallError, Value]

Executes a tool call with optional per-tool timeout and retry.

Executes a tool call with optional per-tool timeout and retry.

When config is default (no timeout, no retry), behavior is identical to execute.

Value parameters

config

Optional timeout and retry policy

ec

ExecutionContext required when timeout or retry is used

request

The tool call request

Attributes

Inherited from:
ToolRegistry
def executeAll(requests: Seq[ToolCallRequest], strategy: ToolExecutionStrategy, config: ToolExecutionConfig)(implicit ec: ExecutionContext): Future[Seq[Either[ToolCallError, Value]]]

Execute multiple tool calls with a configurable strategy.

Execute multiple tool calls with a configurable strategy.

Value parameters

ec

ExecutionContext for async execution

requests

The tool call requests to execute

strategy

Execution strategy (Sequential, Parallel, or ParallelWithLimit)

Attributes

Returns

Future containing results in the same order as requests

Inherited from:
ToolRegistry
def executeAsync(request: ToolCallRequest, config: ToolExecutionConfig)(implicit ec: ExecutionContext): Future[Either[ToolCallError, Value]]

Execute a tool call asynchronously with optional timeout and retry.

Execute a tool call asynchronously with optional timeout and retry.

Value parameters

config

Optional timeout and retry policy

ec

ExecutionContext for async execution

request

The tool call request

Attributes

Inherited from:
ToolRegistry
def executeAsync(request: ToolCallRequest)(implicit ec: ExecutionContext): Future[Either[ToolCallError, Value]]

Execute a tool call asynchronously.

Execute a tool call asynchronously.

Wraps synchronous execution in a Future for non-blocking operation. NOTE: Tool execution typically involves blocking I/O. We use blocking to hint the ExecutionContext to expand its pool if necessary.

Value parameters

ec

ExecutionContext for async execution

request

The tool call request

Attributes

Returns

Future containing the result

Inherited from:
ToolRegistry
def getTool(name: String): Option[ToolFunction[_, _]]

Get a specific tool by name

Get a specific tool by name

Attributes

Inherited from:
ToolRegistry
def getToolDefinitionsSafe(provider: String): Result[Value]

Generate tool definitions in the format expected by a specific LLM provider.

Generate tool definitions in the format expected by a specific LLM provider.

Currently all supported providers (openai, anthropic, gemini) use the same OpenAI-compatible format.

Value parameters

provider

Provider name (case-insensitive): "openai", "anthropic", "gemini"

Attributes

Returns

Right(tools) for supported providers, Left(ValidationError) for unsupported ones

Inherited from:
ToolRegistry

Deprecated and Inherited methods

def getToolDefinitions(provider: String): Value

Generate a specific format of tool definitions for a particular LLM provider.

Generate a specific format of tool definitions for a particular LLM provider.

Value parameters

provider

Provider name (case-insensitive): "openai", "anthropic", "gemini"

Attributes

Throws
java.lang.IllegalArgumentException

for unsupported provider names

Deprecated
[Since version 0.2.9] Use getToolDefinitionsSafe() which returns Result[ujson.Value] for safe error handling
Inherited from:
ToolRegistry