forward clientFactory
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
Reference in New Issue
Block a user