Skip to main content
The MCPClientManager class manages connections to one or more MCP servers and provides methods to interact with their tools, resources, and prompts.

Import

import { MCPClientManager } from "@mcpjam/sdk";

Constructor

new MCPClientManager(servers: ServerConfig)

Parameters

servers
Record<string, StdioServerConfig | HttpServerConfig>
required
A map of server IDs to their configurations.

Server Configuration Types

StdioServerConfig

For subprocess-based MCP servers.
PropertyTypeRequiredDescription
commandstringYesThe command to run (e.g., "node", "python", "npx")
argsstring[]NoCommand arguments
envRecord<string, string>NoEnvironment variables for the subprocess
{
  myServer: {
    command: "node",
    args: ["./server.js", "--port", "3000"],
    env: {
      API_KEY: process.env.API_KEY,
      DEBUG: "true",
    },
  },
}

HttpServerConfig

For remote MCP servers via SSE or Streamable HTTP.
PropertyTypeRequiredDescription
urlstringYesThe server URL (e.g., "https://mcp.example.com/sse")
accessTokenstringNoStatic bearer token added as Authorization: Bearer <token>
requestInitRequestInitNoFetch options including headers for authentication
eventSourceInitEventSourceInitNoSSE-specific options
authProviderOAuthClientProviderNoCustom MCP SDK OAuth provider
refreshTokenstringNoRefresh token used for non-interactive OAuth token exchange and automatic token refresh
clientIdstringNoOAuth client ID. Required when refreshToken is set
clientSecretstringNoOAuth client secret for confidential clients
reconnectionOptionsStreamableHTTPClientTransportOptions["reconnectionOptions"]NoStreamable HTTP reconnection behavior
sessionIdstringNoExisting Streamable HTTP session ID
preferSSEbooleanNoForces SSE instead of Streamable HTTP
{
  remoteServer: {
    url: "https://mcp.asana.com/sse",
    requestInit: {
      headers: {
        Authorization: "Bearer YOUR_TOKEN",
        "X-Custom-Header": "value",
      },
    },
  },
}
Refresh Token Example
{
  remoteServer: {
    url: "https://mcp.example.com/mcp",
    refreshToken: process.env.MCP_REFRESH_TOKEN!,
    clientId: process.env.MCP_CLIENT_ID!,
    clientSecret: process.env.MCP_CLIENT_SECRET,
  },
}
When refreshToken is provided, the SDK will exchange it for an access token during connection and automatically refresh tokens if the server challenges the current token.
refreshToken is mutually exclusive with accessToken, authProvider, and requestInit.headers.Authorization.

Example

const manager = new MCPClientManager({
  // STDIO server
  local: {
    command: "npx",
    args: ["-y", "@modelcontextprotocol/server-everything"],
  },
  // HTTP server
  remote: {
    url: "https://mcp.example.com/sse",
    requestInit: {
      headers: { Authorization: "Bearer token" },
    },
  },
});

Methods

connectToServer()

Establishes a connection to a configured server.
connectToServer(serverId: string): Promise<Client>

Parameters

ParameterTypeDescription
serverIdstringThe server ID from the constructor config

Returns

Promise<Client> - Resolves with the connected MCP client, rejects on failure.

Example

await manager.connectToServer("myServer");

Throws

  • Error if serverId is not in the configuration
  • Error if connection fails (network, subprocess spawn, etc.)

disconnectServer()

Closes the connection to a server and cleans up resources.
disconnectServer(serverId: string): Promise<void>

Parameters

ParameterTypeDescription
serverIdstringThe server ID to disconnect

Returns

Promise<void>

Example

await manager.disconnectServer("myServer");

pingServer()

Sends a ping to check if a server is responsive.
pingServer(serverId: string): void

Parameters

ParameterTypeDescription
serverIdstringThe server ID to ping

Returns

void - This method is synchronous and does not return a value.

Throws

  • Error if the server is not connected
  • Error if the ping fails

Example

try {
  manager.pingServer("myServer");
  console.log("Server is responsive");
} catch (error) {
  console.warn("Server not responding:", error.message);
}

listTools()

Returns all tools available on a server.
listTools(serverId: string): Promise<{ tools: Tool[] }>

Parameters

ParameterTypeDescription
serverIdstringThe server ID

Returns

Promise<{ tools: Tool[] }> - Tool list response from the server.

Tool Object

PropertyTypeDescription
namestringTool identifier
descriptionstringHuman-readable description
inputSchemaobjectJSON Schema for tool arguments

Example

const tools = await manager.listTools("myServer");

for (const tool of tools.tools) {
  console.log(`${tool.name}: ${tool.description}`);
}

executeTool()

Executes a tool and returns the result.
executeTool(
  serverId: string,
  toolName: string,
  args: Record<string, unknown>
): Promise<unknown>

Parameters

ParameterTypeDescription
serverIdstringThe server ID
toolNamestringName of the tool to execute
argsRecord<string, unknown>Arguments to pass to the tool

Returns

Promise<unknown> - The tool’s return value (type depends on the tool).

Example

const result = await manager.executeTool("myServer", "add", {
  a: 5,
  b: 3,
});
console.log(result); // 8

Throws

  • Error if tool doesn’t exist
  • Error if arguments are invalid
  • Error if tool execution fails

listResources()

Returns all resources available on a server.
listResources(serverId: string): Promise<Resource[]>

Parameters

ParameterTypeDescription
serverIdstringThe server ID

Returns

Promise<Resource[]> - Array of resource definitions.

Resource Object

PropertyTypeDescription
namestringResource identifier
uristringResource URI
descriptionstringHuman-readable description
mimeTypestringContent type

Example

const resources = await manager.listResources("myServer");

for (const resource of resources) {
  console.log(`${resource.name}: ${resource.uri}`);
}

readResource()

Reads the content of a resource.
readResource(
  serverId: string,
  params: { uri: string }
): Promise<ResourceContent>

Parameters

ParameterTypeDescription
serverIdstringThe server ID
params.uristringThe resource URI to read

Returns

Promise<ResourceContent> - The resource content.

Example

const content = await manager.readResource("myServer", {
  uri: "file://config.json",
});
console.log(content);

listPrompts()

Returns all prompts available on a server.
listPrompts(serverId: string): Promise<Prompt[]>

Parameters

ParameterTypeDescription
serverIdstringThe server ID

Returns

Promise<Prompt[]> - Array of prompt definitions.

Prompt Object

PropertyTypeDescription
namestringPrompt identifier
descriptionstringHuman-readable description
argumentsPromptArgument[]Expected arguments

Example

const prompts = await manager.listPrompts("myServer");

for (const prompt of prompts) {
  console.log(`${prompt.name}: ${prompt.description}`);
}

getPrompt()

Gets a prompt with optional arguments.
getPrompt(
  serverId: string,
  params: { name: string; arguments?: Record<string, string> }
): Promise<PromptResult>

Parameters

ParameterTypeDescription
serverIdstringThe server ID
params.namestringThe prompt name
params.argumentsRecord<string, string>Optional prompt arguments

Returns

Promise<PromptResult> - The prompt content with messages.

Example

const prompt = await manager.getPrompt("myServer", {
  name: "summarize",
  arguments: { length: "short" },
});
console.log(prompt.messages);

getTools()

Returns all tools from specified servers or all connected servers.
getTools(serverIds?: string[]): Promise<Tool[]>

Parameters

ParameterTypeDescription
serverIdsstring[]Optional. Array of server IDs to fetch tools from. If omitted, returns tools from all connected servers.

Returns

Promise<Tool[]> - Array of tool definitions from all specified servers.

Tool Object

Each tool in the returned array includes:
PropertyTypeDescription
namestringTool identifier
descriptionstringHuman-readable description
inputSchemaobjectJSON Schema for tool arguments
executefunctionFunction to execute the tool with arguments

Example

// Tools from specific servers
const tools = await manager.getTools(["myServer", "anotherServer"]);

// Tools from all connected servers
const allTools = await manager.getTools();

for (const tool of allTools) {
  console.log(`${tool.name}: ${tool.description}`);
}

// Use with TestAgent
const agent = new TestAgent({
  tools: await manager.getTools(),
  model: "anthropic/claude-sonnet-4-20250514",
  apiKey: process.env.ANTHROPIC_API_KEY,
});

const result = await agent.prompt("Add 2 and 3");
console.log(result.getText());
Tools with visibility: ["app"] are automatically filtered out by TestAgent per MCP specification. These tools are callable by apps but should not be exposed to the AI model.

Complete Example

import { MCPClientManager, TestAgent } from "@mcpjam/sdk";

async function main() {
  const manager = new MCPClientManager({
    math: {
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-everything"],
    },
    asana: {
      url: "https://mcp.asana.com/sse",
      requestInit: {
        headers: { Authorization: `Bearer ${process.env.ASANA_TOKEN}` },
      },
    },
  });

  try {
    // Connect
    await manager.connectToServer("math");
    await manager.connectToServer("asana");

    // Direct tool execution
    const sum = await manager.executeTool("math", "add", { a: 10, b: 5 });
    console.log("Sum:", sum);

    // List capabilities
    const mathTools = await manager.listTools("math");
    const asanaTools = await manager.listTools("asana");
    console.log("Math tools:", mathTools.tools.length);
    console.log("Asana tools:", asanaTools.tools.length);

    // Create agent with all tools
    const agent = new TestAgent({
      tools: await manager.getTools(),
      model: "anthropic/claude-sonnet-4-20250514",
      apiKey: process.env.ANTHROPIC_API_KEY,
    });

    const result = await agent.prompt("Add 2 and 3");
    console.log(result.getText());
  } finally {
    await manager.disconnectServer("math");
    await manager.disconnectServer("asana");
  }
}