Consuming Remote MCP Tools¶
registerMcpRemoteTools() imports tools from a remote MCP server into the local ToolRegistry as proxy tools. Each imported tool delegates execution to the remote server via tools/call over Streamable HTTP.
Import¶
import {
registerMcpRemoteTools,
McpRemoteServerConfig,
McpAuth,
RegisterMcpRemoteToolsResult,
} from "@modernpath/agent-framework";
Signature¶
async function registerMcpRemoteTools(
registry: ToolRegistry,
config: McpRemoteServerConfig,
): Promise<RegisterMcpRemoteToolsResult>
| Parameter | Type | Description |
|---|---|---|
registry | ToolRegistry | The tool registry to import tools into. |
config | McpRemoteServerConfig | Remote server configuration. |
McpRemoteServerConfig¶
interface McpRemoteServerConfig {
name: string;
url: string;
auth?: McpAuth;
toolPrefix?: string;
category?: string;
tags?: string[];
allowTools?: string[];
denyTools?: string[];
denyToolPrefix?: string;
timeoutMs?: number;
retries?: number;
}
| Property | Type | Default | Description |
|---|---|---|---|
name | string | -- | Required. Friendly name for diagnostics and tagging. |
url | string | -- | Required. Base URL for the Streamable HTTP MCP endpoint (typically ends with /mcp). |
auth | McpAuth | { type: "none" } | Authentication method. |
toolPrefix | string | "" | Prefix applied to imported tool names (e.g. "acme." turns getTelemetry into acme.getTelemetry). |
category | string | "external" | Category assigned to imported tools in the registry. |
tags | string[] | [] | Additional tags for imported tools. "mcp" and the server name are always added. |
allowTools | string[] | -- | Whitelist of remote tool names to import. If provided, only listed tools are imported. |
denyTools | string[] | -- | Blacklist of remote tool names to skip. |
denyToolPrefix | string | -- | Deny importing tools whose remote name starts with this prefix. Used for loop safety. |
timeoutMs | number | 30000 | Request timeout in milliseconds. |
retries | number | 0 | Number of retry attempts for transient network errors (connection refused, reset, timeout). Does NOT retry HTTP 4xx errors. Progressive delay: 500ms, 1000ms, 2000ms, etc. |
McpAuth¶
type McpAuth =
| { type: "none" }
| { type: "bearer"; getToken: (ctx: { userId: number; auditingId: number }) => Promise<string> | string };
| Type | Description |
|---|---|
{ type: "none" } | No authentication. |
{ type: "bearer", getToken } | Bearer token authentication. getToken is called with the user context from tool execution parameters. |
RegisterMcpRemoteToolsResult¶
interface RegisterMcpRemoteToolsResult {
registered: string[];
skipped: Array<{ tool: string; reason: string }>;
remoteTools: Array<{ name: string; description?: string }>;
}
| Field | Type | Description |
|---|---|---|
registered | string[] | Local names of successfully registered proxy tools. |
skipped | array | Tools that were not imported, with reasons (denied, duplicate, etc.). |
remoteTools | array | All tools discovered on the remote server. |
Handshake Flow¶
The function performs the full MCP lifecycle:
- Initialize -- sends
initializeJSON-RPC request, receives server capabilities and session ID - Notification -- sends
notifications/initializedto complete handshake - Discovery -- calls
tools/listto discover available tools - Registration -- registers each tool as a proxy in the local
ToolRegistry
Session Management¶
The returned proxy tools share a session ID. If the session expires (e.g. server redeployment), the proxy automatically re-establishes the session on the next call. Concurrent callers piggyback on a single re-initialization to avoid duplicate handshakes.
Tool Metadata¶
Each imported tool is registered with metadata that includes:
- The original remote tool's
inputSchemaandoutputSchema(stored asschema.inputJsonSchemaandschema.outputJsonSchema) - Category from config (default:
"external") - Tags: config tags plus
"mcp"and the server name
Agents can retrieve schemas at runtime via registry.getMetadata(toolName)?.schema?.outputJsonSchema.
Code Example¶
import { ToolRegistry, registerMcpRemoteTools } from "@modernpath/agent-framework";
const registry = new ToolRegistry();
// Import tools from a remote MCP server
const result = await registerMcpRemoteTools(registry, {
name: "acme-iot",
url: "https://api.acme.com/mcp",
auth: {
type: "bearer",
getToken: async ({ userId, auditingId }) => {
return await authService.getServiceToken(userId, auditingId);
},
},
toolPrefix: "acme.",
category: "telemetry",
tags: ["iot", "building"],
allowTools: ["getTelemetryBundle", "getAlerts", "getDeviceStatus"],
denyToolPrefix: "internal.",
timeoutMs: 30000,
retries: 2,
});
console.log("Registered tools:", result.registered);
// ["acme.getTelemetryBundle", "acme.getAlerts", "acme.getDeviceStatus"]
console.log("Skipped:", result.skipped);
// [{ tool: "internal.debug", reason: "Denied by denyToolPrefix (internal.)" }]
// Use the imported tool
const telemetry = await registry.execute("acme.getTelemetryBundle", {
userId: 1,
auditingId: 100,
sensorId: "sensor-123",
timeRange: "24h",
});
// Access tool schema
const schema = registry.getMetadata("acme.getTelemetryBundle")?.schema;
console.log(schema?.outputJsonSchema);
Related Pages¶
- Exposing Tools -- creating an MCP server from your registry
- Loop Safety -- preventing MCP call loops
- Schema Resources -- discovering tool schemas
- Core / ToolRegistry -- the registry that stores imported tools