mastra-ai/mastra · error · Error
MCPClient was initialized multiple times with the same confi
Error message
MCPClient was initialized multiple times with the same configuration options.
This error is intended to prevent memory leaks.
To fix this you have three different options:
1. If you need multiple MCPClient class instances with identical server configurations, set an id when configuring: new MCPClient({ id: "my-unique-id" })
2. Call "await client.disconnect()" after you're done using the client and before you recreate another instance with the same options. If the identical MCPClient instance is already closed at the time
3. If you only need one instance of MCPClient in your app, refactor your code so it's only created one time (ex. move it out of a loop into a higher scope code block) What it means
MCPClient keeps a registry (mcpClientInstances) keyed by an id derived from its configuration. Constructing a second MCPClient with identical options and no explicit id would leak the first instance's connections, so the constructor throws this plain Error with the three documented remedies. It is a guard against duplicate long-lived clients (duplicated transports, toolsets, and event handlers).
Source
Thrown at packages/mcp/src/client/configuration.ts:175
this.id = args.id;
const cached = mcpClientInstances.get(this.id);
if (cached && !equal(cached.serverConfigs, args.servers)) {
const existingInstance = mcpClientInstances.get(this.id);
if (existingInstance) {
void existingInstance.disconnect();
mcpClientInstances.delete(this.id);
}
}
} else {
this.id = this.makeId();
}
// to prevent memory leaks return the same MCP server instance when configured the same way multiple times
const existingInstance = mcpClientInstances.get(this.id);
if (existingInstance) {
if (!args.id) {
throw new Error(`MCPClient was initialized multiple times with the same configuration options.
This error is intended to prevent memory leaks.
To fix this you have three different options:
1. If you need multiple MCPClient class instances with identical server configurations, set an id when configuring: new MCPClient({ id: "my-unique-id" })
2. Call "await client.disconnect()" after you're done using the client and before you recreate another instance with the same options. If the identical MCPClient instance is already closed at the time of re-creating it, you will not see this error.
3. If you only need one instance of MCPClient in your app, refactor your code so it's only created one time (ex. move it out of a loop into a higher scope code block)
`);
}
return existingInstance;
}
mcpClientInstances.set(this.id, this);
this.addToInstanceCache();
return this;
}
/**View on GitHub (pinned to 75dd419e61)
Solutions
- Add a stable explicit id: new MCPClient({ id: 'my-unique-id', ... }) so identical configurations reuse the same registered instance.
- Call await client.disconnect() when done, before creating another instance with the same options.
- Refactor to a singleton: create the client once at a higher scope (module level / app init) instead of per request, loop iteration, or render.
- In dev/HMR, guard construction with a global singleton (e.g. globalThis.__mcpClient ??= new MCPClient(...)).
Example fix
// before: per-request construction duplicates the client
async function handler() {
const mcp = new MCPClient({ servers: { filesystem: { command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '/data'] } } });
return mcp.getTools();
}
// after: ided singleton
const mcp = new MCPClient({ id: 'fs-tools', servers: { filesystem: { command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '/data'] } } });
async function handler() {
return mcp.getTools();
} Defensive patterns
Strategy: validation
Validate before calling
// Check whether an identical instance is already registered before constructing
const id = 'fs-tools';
// MCPClient dedupes instances by explicit id, so always pass one:
const mcp = globalThis.__mcpClient ?? (globalThis.__mcpClient = new MCPClient({ id, servers: {...} })); Type guard
function hasExplicitId(opts: ConstructorParameters<typeof MCPClient>[0]): boolean {
return typeof (opts as { id?: string }).id === 'string' && (opts as { id?: string }).id!.length > 0;
} Try / catch
let mcp: MCPClient;
try {
mcp = new MCPClient({ servers: {...} });
} catch (e) {
if (e instanceof Error && e.message.includes('initialized multiple times')) {
mcp = MCPClient.getInstance?.() ?? new MCPClient({ id: 'shared-client', servers: {...} });
} else throw e;
} Prevention
- Always pass an explicit id when constructing MCPClient.
- Create the client once at module/app scope; never inside request handlers, loops, or render bodies.
- Always await client.disconnect() during shutdown or before re-creating with the same options.
- Use a globalThis singleton guard to survive HMR/double module evaluation in dev.
When it happens
Trigger: Calling new MCPClient({...same servers/options...}) twice (or more) while the first instance is still connected and no explicit id was supplied — commonly inside loops, React render/effect bodies, serverless cold-start handlers, or module-level accidental double-imports.
Common situations: Creating the client inside a request handler or component render; dev-mode double evaluation (HMR) of a module that constructs the client at top level; serverless functions constructing per invocation without disconnect; copy-pasting client setup in two files both executed.
Related errors
- MCP client was disconnected while recovering the failed tran
- MastraAuthBetterAuth is not initialized — init() must run fi
- Shared browser not launched. Call createSharedSession() firs
- Browser not launched
- App deletion failed: ${data.error}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/84b7f210445eb0b9.
Report an issue: GitHub.