forward clientFactory

This commit is contained in:
Simon Knott
2025-08-12 10:12:49 +02:00
parent e884b3aacb
commit 001fa6f2fb
4 changed files with 12 additions and 15 deletions

View File

@@ -20,10 +20,10 @@ import { BrowserContextFactory } from './browserContextFactory.js';
import { BrowserServerBackend } from './browserServerBackend.js'; import { BrowserServerBackend } from './browserServerBackend.js';
import { InProcessTransport } from './mcp/inProcessTransport.js'; import { InProcessTransport } from './mcp/inProcessTransport.js';
import * as mcpServer from './mcp/server.js'; import * as mcpServer from './mcp/server.js';
import { packageJSON } from './package.js';
import type { FullConfig } from './config.js'; import type { FullConfig } from './config.js';
import type { ClientFactory } from './mcp/proxyBackend.js'; import type { ClientFactory } from './mcp/proxyBackend.js';
import type { Implementation } from '@modelcontextprotocol/sdk/types.js';
export class InProcessClientFactory implements ClientFactory { export class InProcessClientFactory implements ClientFactory {
name: string; name: string;
@@ -39,11 +39,8 @@ export class InProcessClientFactory implements ClientFactory {
this._config = config; this._config = config;
} }
async create(): Promise<Client> { async create(clientVersion: Implementation): Promise<Client> {
const client = new Client({ const client = new Client(clientVersion);
name: this.name,
version: packageJSON.version
});
const server = mcpServer.createServer(new BrowserServerBackend(this._config, this._contextFactory), false); const server = mcpServer.createServer(new BrowserServerBackend(this._config, this._contextFactory), false);
await client.connect(new InProcessTransport(server)); await client.connect(new InProcessTransport(server));
await client.ping(); await client.ping();

View File

@@ -23,13 +23,14 @@ import { packageJSON } from '../package.js';
import { logUnhandledError } from '../log.js'; import { logUnhandledError } from '../log.js';
import type { Client } from '@modelcontextprotocol/sdk/client/index.js'; import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
import type { Implementation } from '@modelcontextprotocol/sdk/types.js';
type NonEmptyArray<T> = [T, ...T[]]; type NonEmptyArray<T> = [T, ...T[]];
export type ClientFactory = { export type ClientFactory = {
name: string; name: string;
description: string; description: string;
create(options: any): Promise<Client>; create(clientVersion: Implementation, options: any): Promise<Client>;
}; };
export type ClientFactoryList = NonEmptyArray<ClientFactory>; export type ClientFactoryList = NonEmptyArray<ClientFactory>;
@@ -42,6 +43,7 @@ export class ProxyBackend implements ServerBackend {
private _currentClient: Client | undefined; private _currentClient: Client | undefined;
private _contextSwitchTool: Tool<any>; private _contextSwitchTool: Tool<any>;
private _tools: ToolSchema<any>[] = []; private _tools: ToolSchema<any>[] = [];
private _server?: Server;
constructor(clientFactories: ClientFactoryList) { constructor(clientFactories: ClientFactoryList) {
this._clientFactories = clientFactories; this._clientFactories = clientFactories;
@@ -49,6 +51,7 @@ export class ProxyBackend implements ServerBackend {
} }
async initialize(server: Server): Promise<void> { async initialize(server: Server): Promise<void> {
this._server = server;
await this._setCurrentClient(this._clientFactories[0], undefined); await this._setCurrentClient(this._clientFactories[0], undefined);
} }
@@ -120,7 +123,7 @@ export class ProxyBackend implements ServerBackend {
private async _setCurrentClient(factory: ClientFactory, options: any) { private async _setCurrentClient(factory: ClientFactory, options: any) {
await this._currentClient?.close(); await this._currentClient?.close();
this._currentClient = await factory.create(options); this._currentClient = await factory.create(this._server!.getClientVersion()!, options);
const tools = await this._currentClient.listTools(); const tools = await this._currentClient.listTools();
this._tools = tools.tools.map(tool => ({ this._tools = tools.tools.map(tool => ({
name: tool.name, name: tool.name,

View File

@@ -77,7 +77,7 @@ export function createServer(backend: ServerBackend, runHeartbeat: boolean): Ser
name: tool.name, name: tool.name,
description: tool.description, description: tool.description,
// TODO: we expect inputSchema to be a zod schema, but in the out-of-process case it's already a json schema. // TODO: we expect inputSchema to be a zod schema, but in the out-of-process case it's already a json schema.
// we should probably move the "zodToJsonSchema" call into defineTool. // we should move the "zodToJsonSchema" call into defineTool.
inputSchema: tool.inputSchema.$schema ? tool.inputSchema : zodToJsonSchema(tool.inputSchema), inputSchema: tool.inputSchema.$schema ? tool.inputSchema : zodToJsonSchema(tool.inputSchema),
annotations: { annotations: {
title: tool.title, title: tool.title,

View File

@@ -17,7 +17,7 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { FullConfig } from '../config.js'; import { FullConfig } from '../config.js';
import { ClientFactory } from '../mcp/proxyBackend.js'; import { ClientFactory } from '../mcp/proxyBackend.js';
import { packageJSON } from '../package.js'; import type { Implementation } from '@modelcontextprotocol/sdk/types.js';
class VSCodeClientFactory implements ClientFactory { class VSCodeClientFactory implements ClientFactory {
name = 'vscode'; name = 'vscode';
@@ -25,16 +25,13 @@ class VSCodeClientFactory implements ClientFactory {
constructor(private readonly _config: FullConfig) {} constructor(private readonly _config: FullConfig) {}
async create(options: any): Promise<Client> { async create(clientVersion: Implementation, options: any): Promise<Client> {
if (typeof options.connectionString !== 'string') if (typeof options.connectionString !== 'string')
throw new Error('Missing options.connectionString'); throw new Error('Missing options.connectionString');
if (typeof options.lib !== 'string') if (typeof options.lib !== 'string')
throw new Error('Missing options.library'); throw new Error('Missing options.library');
const client = new Client({ const client = new Client(clientVersion);
name: this.name,
version: packageJSON.version
});
await client.connect(new StdioClientTransport({ await client.connect(new StdioClientTransport({
command: process.execPath, command: process.execPath,
cwd: process.cwd(), cwd: process.cwd(),