Overview
MCPClientManager
is the central orchestration class for managing multiple MCP (Model Context Protocol) server connections within MCPJam Inspector. It provides a high-level abstraction over the @modelcontextprotocol/sdk
Client class, handling connection lifecycle, transport selection, and unified access to MCP capabilities across multiple servers.
Location: sdk/mcp-client-manager/index.ts
Key Responsibilities:
- Managing multiple MCP server connections with unique identifiers
- Auto-detecting and configuring appropriate transports (STDIO, SSE, Streamable HTTP)
- Providing unified APIs for tools, resources, prompts, and elicitations
- Handling connection state, reconnection, and error recovery
- Integrating with AI frameworks (Vercel AI SDK)
- Supporting elicitation (interactive prompts from MCP servers)
Architecture
Class Structure
Server Configuration Types
The manager supports two transport types, automatically selected based on configuration:STDIO Configuration
HTTP/SSE Configuration
Base Configuration
Core Concepts
1. Connection Lifecycle
The manager maintains three connection states:disconnected
: No client exists, no connection attempt in progressconnecting
: Connection attempt in progress (tracked viastate.promise
)connected
: Client successfully connected and ready
2. Transport Selection
The manager automatically selects the appropriate transport:-
STDIO Transport: Used when config has
command
property- Spawns subprocess with
StdioClientTransport
- Manages stdin/stdout/stderr streams
- Includes default environment variables
- Spawns subprocess with
-
HTTP Transport: Used when config has
url
property- Streamable HTTP (default): Bidirectional streaming over HTTP
- SSE (fallback): Server-Sent Events for unidirectional streaming
- Auto-fallback: Tries Streamable HTTP first, falls back to SSE on failure
- Force SSE: Set
preferSSE: true
or use URL ending in/sse
3. Tool Metadata Caching
The manager caches tool_meta
fields for OpenAI Apps SDK compatibility:
getAllToolsMetadata(serverId)
to get all tool metadata for a server.
4. Elicitation Support
Elicitation allows MCP servers to request interactive input during tool execution: Two modes:- Server-specific handler: Set per-server via
setElicitationHandler(serverId, handler)
- Global callback: Set globally via
setElicitationCallback(callback)
5. JSON-RPC Logging
RPC logging can be enabled at three levels:- Global default:
new MCPClientManager({}, { defaultLogJsonRpc: true })
- Global custom logger:
new MCPClientManager({}, { rpcLogger: (event) => {...} })
- Per-server:
{ serverId: { ..., logJsonRpc: true } }
orrpcLogger: (event) => {...}
LoggingTransport
that intercepts all JSON-RPC messages.
Usage Patterns in MCPJam Inspector
1. App Initialization
2. Chat Endpoint
3. HTTP Bridge
4. Managing Server Connections
API Reference
Connection Management
Connect to an MCP server. Throws if server ID already exists. Returns the connected Client instance.
Disconnect from a server and clean up resources.
Disconnect from all servers and reset state.
Remove server from state without attempting disconnection.
Get array of all server IDs.
Check if a server is registered.
Get status and config for all servers.
Get connection status:
"connected"
| "connecting"
| "disconnected"
.Get configuration for a server.
Tools
List tools for a single server. Caches metadata. Returns empty list if unsupported.
Get tools from multiple servers (or all if not specified). Returns flattened list.
executeTool
(serverId: string, toolName: string, args: Record<string, unknown>, options?) => Promise<CallToolResult>
Execute a tool on a specific server.
Get tools in Vercel AI SDK format. Automatically wires up tool execution. Each tool has
_serverId
metadata attached.Options:schemas?: ToolSchemaOverrides | "automatic"
- Control schema conversion
Get all tool
_meta
fields for OpenAI Apps SDK.Send ping to server.
Resources
List available resources. Returns empty if unsupported.
Read a resource by URI.
Subscribe to resource updates.
Unsubscribe from resource updates.
List resource templates.
Prompts
List available prompts. Returns empty if unsupported.
getPrompt
(serverId: string, params: { name: string, arguments?: Record<string, string> }, options?) => Promise<GetPromptResult>
Get a prompt with optional arguments.
Notifications
addNotificationHandler
(serverId: string, schema: NotificationSchema, handler: NotificationHandler) => void
Add a notification handler for a server.
Handle
resources/list_changed
notifications.Handle
resources/updated
notifications.Handle
prompts/list_changed
notifications.Elicitation
Set server-specific elicitation handler.
Remove server-specific handler.
Set global elicitation callback (used if no server-specific handler).
Remove global callback.
Get map of pending elicitation promise resolvers.
Resolve a pending elicitation. Returns
true
if found.Advanced
Get raw MCP SDK Client instance for advanced usage.
Get session ID for Streamable HTTP servers.
Examples
Example 1: Basic Setup with Multiple Servers
Example 2: Vercel AI SDK Integration
Example 3: Dynamic Server Management
Example 4: Resource Subscriptions
Example 5: Custom RPC Logging
Best Practices
Connection Management
DO:
- Use unique, descriptive server IDs
- Check connection status before operations
- Handle connection errors gracefully
- Clean up connections when no longer needed
- Reuse server IDs without disconnecting first
- Assume connections are always ready
- Leave connections open indefinitely
- Ignore connection state changes
Tool Execution
DO:
- Validate tool arguments before execution
- Set appropriate timeouts for long-running tools
- Handle tool errors with meaningful messages
- Use
getToolsForAiSdk
for AI framework integration
- Execute tools without checking server status
- Use hardcoded tool names without verification
- Ignore tool execution errors
- Mix manual tool calling with AI SDK integration
Elicitation Handling
DO:
- Set timeouts for elicitation responses
- Clean up pending elicitations on errors
- Use server-specific handlers for custom logic
- Clear callbacks when done to prevent leaks
- Leave elicitations pending indefinitely
- Forget to respond to elicitation requests
- Mix server-specific and global handlers unexpectedly
- Ignore elicitation errors
Performance
DO:
- Cache tool metadata when possible
- Reuse connections across requests
- Use parallel operations with
getTools()
- Monitor connection health
- Create new connections for each request
- Poll for updates without subscriptions
- Ignore connection pool limits
- Skip cleanup on shutdown
Troubleshooting
"MCP server is already connected"
"MCP server is already connected"
Cause: Attempting to connect with a server ID that’s already in use.Solution: Disconnect first or use a different ID.
"MCP server is not connected"
"MCP server is not connected"
Cause: Attempting operations on a disconnected server.Solution: Check
getConnectionStatus()
and connect if needed."Method not found" or "Method not implemented"
"Method not found" or "Method not implemented"
Cause: Server doesn’t support the requested capability.Solution: The manager returns empty results for unsupported methods (tools/list, resources/list, prompts/list).
Transport connection failures
Transport connection failures
Cause: Network issues, server not running, or incorrect configuration.Solution:
- Verify server is accessible
- Check configuration (URL, command, args)
- Review server logs for errors
- Use RPC logging to debug protocol issues
Related Documentation
See Also
sdk/mcp-client-manager/README.md
- Public-facing documentationsdk/mcp-client-manager/goal.md
- Original design goalssdk/mcp-client-manager/tool-converters.ts
- AI SDK conversion logicserver/routes/mcp/chat.ts
- Chat endpoint usageserver/services/mcp-http-bridge.ts
- HTTP bridge implementation