统一多端模态的消息桥接层
This commit is contained in:
parent
0bea084c35
commit
354380cf23
@ -14,10 +14,11 @@ import Sidebar from '@/components/sidebar/index.vue';
|
||||
import MainPanel from '@/components/main-panel/index.vue';
|
||||
import { setDefaultCss } from './hook/css';
|
||||
import { greenLog, pinkLog } from './views/setting/util';
|
||||
import { acquireVsCodeApi, useMessageBridge } from './api/message-bridge';
|
||||
import { connectionArgs, connectionMethods, doWebConnect, doVscodeConnect, loadEnvVar } from './views/connect/connection';
|
||||
import { useMessageBridge } from './api/message-bridge';
|
||||
import { connectionArgs, connectionMethods, doConnect, loadEnvVar } from './views/connect/connection';
|
||||
import { loadSetting } from './hook/setting';
|
||||
import { loadPanels } from './hook/panel';
|
||||
import { getPlatform } from './api/platform';
|
||||
|
||||
const bridge = useMessageBridge();
|
||||
|
||||
@ -28,51 +29,10 @@ bridge.addCommandListener('hello', data => {
|
||||
}, { once: true });
|
||||
|
||||
|
||||
function initDebug() {
|
||||
|
||||
setTimeout(async () => {
|
||||
// 初始化 设置
|
||||
loadSetting();
|
||||
|
||||
// 初始化环境变量
|
||||
loadEnvVar();
|
||||
|
||||
// 尝试连接
|
||||
await doWebConnect();
|
||||
|
||||
// 初始化 tab
|
||||
loadPanels();
|
||||
|
||||
}, 200);
|
||||
}
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
async function initProduce() {
|
||||
// TODO: get from vscode
|
||||
connectionArgs.commandString = 'mcp run ../servers/main.py';
|
||||
connectionMethods.current = 'STDIO';
|
||||
|
||||
// 初始化 设置
|
||||
loadSetting();
|
||||
|
||||
// 初始化环境变量
|
||||
loadEnvVar();
|
||||
|
||||
// 尝试连接
|
||||
await doVscodeConnect();
|
||||
|
||||
// 初始化 tab
|
||||
await loadPanels();
|
||||
|
||||
if (route.name !== 'debug') {
|
||||
router.replace('/debug');
|
||||
router.push('/debug');
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
// 初始化 css
|
||||
setDefaultCss();
|
||||
|
||||
@ -82,11 +42,36 @@ onMounted(() => {
|
||||
|
||||
pinkLog('OpenMCP Client 启动');
|
||||
|
||||
if (acquireVsCodeApi === undefined) {
|
||||
initDebug();
|
||||
} else {
|
||||
initProduce();
|
||||
const platform = getPlatform();
|
||||
|
||||
// 跳转到首页
|
||||
if (platform !== 'web') {
|
||||
if (route.name !== 'debug') {
|
||||
router.replace('/debug');
|
||||
router.push('/debug');
|
||||
}
|
||||
}
|
||||
|
||||
// 进行桥接
|
||||
await bridge.awaitForWebsockt();
|
||||
|
||||
pinkLog('准备请求设置');
|
||||
|
||||
// 加载全局设置
|
||||
loadSetting();
|
||||
|
||||
// 设置环境变量
|
||||
loadEnvVar();
|
||||
|
||||
// 尝试进行初始化连接
|
||||
await doConnect({
|
||||
namespace: platform,
|
||||
updateCommandString: true
|
||||
});
|
||||
|
||||
// loading panels
|
||||
await loadPanels();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { pinkLog } from '@/views/setting/util';
|
||||
import { onUnmounted, ref } from 'vue';
|
||||
import { pinkLog, redLog } from '@/views/setting/util';
|
||||
import { acquireVsCodeApi, electronApi, getPlatform } from './platform';
|
||||
import { ref } from 'vue';
|
||||
|
||||
export interface VSCodeMessage {
|
||||
command: string;
|
||||
@ -15,8 +16,6 @@ export interface RestFulResponse {
|
||||
export type MessageHandler = (message: VSCodeMessage) => void;
|
||||
export type CommandHandler = (data: any) => void;
|
||||
|
||||
export const acquireVsCodeApi = (window as any)['acquireVsCodeApi'];
|
||||
|
||||
interface AddCommandListenerOption {
|
||||
once: boolean // 只调用一次就销毁
|
||||
}
|
||||
@ -24,27 +23,36 @@ interface AddCommandListenerOption {
|
||||
class MessageBridge {
|
||||
private ws: WebSocket | null = null;
|
||||
private handlers = new Map<string, Set<CommandHandler>>();
|
||||
public isConnected = ref(false);
|
||||
private isConnected: Promise<boolean> | null = null;
|
||||
|
||||
constructor(private wsUrl: string = 'ws://localhost:8080') {
|
||||
this.init();
|
||||
}
|
||||
|
||||
private init() {
|
||||
// 环境检测优先级:
|
||||
// 1. VS Code WebView 环境
|
||||
// 2. 浏览器 WebSocket 环境
|
||||
if (typeof acquireVsCodeApi !== 'undefined') {
|
||||
this.setupVSCodeListener();
|
||||
pinkLog('当前模式:release');
|
||||
} else {
|
||||
this.setupWebSocket();
|
||||
pinkLog('当前模式:debug');
|
||||
|
||||
const platform = getPlatform();
|
||||
|
||||
switch (platform) {
|
||||
case 'vscode':
|
||||
this.setupVsCodeListener();
|
||||
pinkLog('当前模式: vscode');
|
||||
break;
|
||||
|
||||
case 'electron':
|
||||
this.setupElectronListener();
|
||||
pinkLog('当前模式: electron');
|
||||
break;
|
||||
|
||||
case 'web':
|
||||
this.setupWebSocket();
|
||||
pinkLog('当前模式: web');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// VS Code 环境监听
|
||||
private setupVSCodeListener() {
|
||||
private setupVsCodeListener() {
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
window.addEventListener('message', (event: MessageEvent<VSCodeMessage>) => {
|
||||
@ -52,17 +60,12 @@ class MessageBridge {
|
||||
});
|
||||
|
||||
this.postMessage = (message) => vscode.postMessage(message);
|
||||
this.isConnected.value = true;
|
||||
}
|
||||
|
||||
// WebSocket 环境连接
|
||||
private setupWebSocket() {
|
||||
this.ws = new WebSocket(this.wsUrl);
|
||||
|
||||
this.ws.onopen = () => {
|
||||
this.isConnected.value = true;
|
||||
};
|
||||
|
||||
this.ws.onmessage = (event) => {
|
||||
try {
|
||||
const message = JSON.parse(event.data) as VSCodeMessage;
|
||||
@ -74,16 +77,41 @@ class MessageBridge {
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
this.isConnected.value = false;
|
||||
redLog('WebSocket connection closed');
|
||||
};
|
||||
|
||||
this.postMessage = (message) => {
|
||||
if (this.ws?.readyState === WebSocket.OPEN) {
|
||||
console.log(message);
|
||||
|
||||
console.log('send', { command: message.command });
|
||||
this.ws.send(JSON.stringify(message));
|
||||
}
|
||||
};
|
||||
|
||||
const ws = this.ws;
|
||||
|
||||
this.isConnected = new Promise<boolean>((resolve, reject) => {
|
||||
ws.onopen = () => {
|
||||
resolve(true);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async awaitForWebsockt() {
|
||||
if (this.isConnected) {
|
||||
await this.isConnected;
|
||||
}
|
||||
}
|
||||
|
||||
private setupElectronListener() {
|
||||
electronApi.onReply((event: MessageEvent<VSCodeMessage>) => {
|
||||
console.log(event);
|
||||
this.dispatchMessage(event.data);
|
||||
});
|
||||
|
||||
this.postMessage = (message) => {
|
||||
console.log(message);
|
||||
electronApi.sendToMain(message);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,6 +204,6 @@ export function useMessageBridge() {
|
||||
postMessage: bridge.postMessage.bind(bridge),
|
||||
addCommandListener: bridge.addCommandListener.bind(bridge),
|
||||
commandRequest: bridge.commandRequest.bind(bridge),
|
||||
isConnected: bridge.isConnected
|
||||
awaitForWebsockt: bridge.awaitForWebsockt.bind(bridge)
|
||||
};
|
||||
}
|
15
renderer/src/api/platform.ts
Normal file
15
renderer/src/api/platform.ts
Normal file
@ -0,0 +1,15 @@
|
||||
export type OpenMcpSupportPlatform = 'web' | 'vscode' | 'electron';
|
||||
|
||||
export const acquireVsCodeApi = (window as any)['acquireVsCodeApi'];
|
||||
|
||||
export const electronApi = (window as any)['electronApi'];
|
||||
|
||||
export function getPlatform(): OpenMcpSupportPlatform {
|
||||
if (typeof acquireVsCodeApi !== 'undefined') {
|
||||
return 'vscode';
|
||||
} else if (typeof electronApi !== 'undefined') {
|
||||
return 'electron';
|
||||
} else {
|
||||
return 'web';
|
||||
}
|
||||
}
|
@ -3,31 +3,25 @@ import { llmManager, llms } from "@/views/setting/llm";
|
||||
import { pinkLog } from "@/views/setting/util";
|
||||
import I18n from '@/i18n/index';
|
||||
|
||||
export function loadSetting() {
|
||||
export async function loadSetting() {
|
||||
const bridge = useMessageBridge();
|
||||
|
||||
bridge.addCommandListener('setting/load', data => {
|
||||
if (data.code !== 200) {
|
||||
pinkLog('配置加载失败');
|
||||
console.log(data.msg);
|
||||
const data = await bridge.commandRequest('setting/load');
|
||||
if (data.code !== 200) {
|
||||
pinkLog('配置加载失败');
|
||||
console.log(data.msg);
|
||||
|
||||
} else {
|
||||
const persistConfig = data.msg;
|
||||
pinkLog('配置加载成功');
|
||||
} else {
|
||||
const persistConfig = data.msg;
|
||||
pinkLog('配置加载成功');
|
||||
|
||||
llmManager.currentModelIndex = persistConfig.MODEL_INDEX;
|
||||
I18n.global.locale.value = persistConfig.LANG;
|
||||
llmManager.currentModelIndex = persistConfig.MODEL_INDEX;
|
||||
I18n.global.locale.value = persistConfig.LANG;
|
||||
|
||||
persistConfig.LLM_INFO.forEach((element: any) => {
|
||||
llms.push(element);
|
||||
});
|
||||
}
|
||||
|
||||
}, { once: true });
|
||||
|
||||
bridge.postMessage({
|
||||
command: 'setting/load'
|
||||
});
|
||||
persistConfig.LLM_INFO.forEach((element: any) => {
|
||||
llms.push(element);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function saveSetting(saveHandler?: () => void) {
|
||||
|
@ -3,6 +3,7 @@ import { reactive } from 'vue';
|
||||
import { pinkLog } from '../setting/util';
|
||||
import { arrowMiddleware, ElMessage } from 'element-plus';
|
||||
import { ILaunchSigature } from '@/hook/type';
|
||||
import { OpenMcpSupportPlatform } from '@/api/platform';
|
||||
|
||||
export const connectionMethods = reactive({
|
||||
current: 'STDIO',
|
||||
@ -69,15 +70,21 @@ export interface McpOptions {
|
||||
clientVersion?: string;
|
||||
}
|
||||
|
||||
export async function doWebConnect(option: { updateCommandString?: boolean } = {}) {
|
||||
export async function doConnect(
|
||||
option: {
|
||||
namespace: OpenMcpSupportPlatform
|
||||
updateCommandString?: boolean
|
||||
}
|
||||
) {
|
||||
const {
|
||||
// updateCommandString 为 true 代表是初始化阶段
|
||||
namespace,
|
||||
updateCommandString = true
|
||||
} = option;
|
||||
|
||||
if (updateCommandString) {
|
||||
pinkLog('请求启动参数');
|
||||
const connectionItem = await getLaunchSignature('web/launch-signature');
|
||||
const connectionItem = await getLaunchSignature(namespace + '/launch-signature');
|
||||
|
||||
if (connectionItem.type ==='stdio') {
|
||||
connectionMethods.current = 'STDIO';
|
||||
@ -98,54 +105,13 @@ export async function doWebConnect(option: { updateCommandString?: boolean } = {
|
||||
}
|
||||
|
||||
if (connectionMethods.current === 'STDIO') {
|
||||
await launchStdio();
|
||||
await launchStdio(namespace);
|
||||
} else {
|
||||
await launchSSE();
|
||||
await launchSSE(namespace);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description vscode 中初始化启动
|
||||
*/
|
||||
export async function doVscodeConnect(option: { updateCommandString?: boolean } = {}) {
|
||||
// 本地开发只用 IPC 进行启动
|
||||
// 后续需要考虑到不同的连接方式
|
||||
|
||||
const {
|
||||
// updateCommandString 为 true 代表是初始化阶段
|
||||
updateCommandString = true
|
||||
} = option;
|
||||
|
||||
if (updateCommandString) {
|
||||
pinkLog('请求启动参数');
|
||||
const connectionItem = await getLaunchSignature('vscode/launch-signature');
|
||||
|
||||
if (connectionItem.type ==='stdio') {
|
||||
connectionMethods.current = 'STDIO';
|
||||
connectionArgs.commandString = connectionItem.commandString;
|
||||
connectionArgs.cwd = connectionItem.cwd;
|
||||
|
||||
if (connectionArgs.commandString.length === 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
connectionMethods.current = 'SSE';
|
||||
connectionArgs.urlString = connectionItem.url;
|
||||
|
||||
if (connectionArgs.urlString.length === 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (connectionMethods.current === 'STDIO') {
|
||||
await launchStdio();
|
||||
} else {
|
||||
await launchSSE();
|
||||
}
|
||||
}
|
||||
|
||||
async function launchStdio() {
|
||||
async function launchStdio(namespace: string) {
|
||||
const bridge = useMessageBridge();
|
||||
const env = makeEnv();
|
||||
|
||||
@ -193,7 +159,7 @@ async function launchStdio() {
|
||||
};
|
||||
|
||||
bridge.postMessage({
|
||||
command: 'vscode/update-connection-sigature',
|
||||
command: namespace + '/update-connection-sigature',
|
||||
data: JSON.parse(JSON.stringify(clientStdioConnectionItem))
|
||||
});
|
||||
|
||||
@ -210,7 +176,7 @@ async function launchStdio() {
|
||||
}
|
||||
}
|
||||
|
||||
async function launchSSE() {
|
||||
async function launchSSE(namespace: string) {
|
||||
const bridge = useMessageBridge();
|
||||
const env = makeEnv();
|
||||
|
||||
@ -247,7 +213,7 @@ async function launchSSE() {
|
||||
};
|
||||
|
||||
bridge.postMessage({
|
||||
command: 'vscode/update-connection-sigature',
|
||||
command: namespace + '/update-connection-sigature',
|
||||
data: JSON.parse(JSON.stringify(clientSseConnectionItem))
|
||||
});
|
||||
|
||||
@ -265,23 +231,11 @@ async function launchSSE() {
|
||||
}
|
||||
|
||||
|
||||
async function getLaunchSignature(signatureName: string) {
|
||||
const bridge = useMessageBridge();
|
||||
const { code, msg } = await bridge.commandRequest(signatureName);
|
||||
|
||||
function getLaunchSignature(signatureName: string) {
|
||||
return new Promise<ILaunchSigature>((resolve, reject) => {
|
||||
// 与 vscode 进行同步
|
||||
const bridge = useMessageBridge();
|
||||
|
||||
bridge.addCommandListener(signatureName, data => {
|
||||
pinkLog('收到启动参数');
|
||||
resolve(data.msg);
|
||||
|
||||
}, { once: true });
|
||||
|
||||
bridge.postMessage({
|
||||
command: signatureName,
|
||||
data: {}
|
||||
});
|
||||
})
|
||||
return msg;
|
||||
}
|
||||
|
||||
export function doReconnect() {
|
||||
|
@ -29,15 +29,14 @@ import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
import { connectionResult, doWebConnect, doVscodeConnect } from './connection';
|
||||
import { connectionResult, doConnect } from './connection';
|
||||
|
||||
import ConnectionMethod from './connection-method.vue';
|
||||
import ConnectionArgs from './connection-args.vue';
|
||||
import EnvVar from './env-var.vue';
|
||||
|
||||
import ConnectionLog from './connection-log.vue';
|
||||
|
||||
import { acquireVsCodeApi } from '@/api/message-bridge';
|
||||
import { getPlatform } from '@/api/platform';
|
||||
|
||||
defineComponent({ name: 'connect' });
|
||||
|
||||
@ -46,11 +45,9 @@ const isLoading = ref(false);
|
||||
async function suitableConnect() {
|
||||
isLoading.value = true;
|
||||
|
||||
if (acquireVsCodeApi === undefined) {
|
||||
await doWebConnect({ updateCommandString: false });
|
||||
} else {
|
||||
await doVscodeConnect({ updateCommandString: false });
|
||||
}
|
||||
const plaform = getPlatform();
|
||||
|
||||
await doConnect({ namespace: plaform, updateCommandString: false })
|
||||
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"serve": "ts-node-dev --respawn --transpile-only src/main.ts",
|
||||
"build": "tsc && webpack --config webpack.config.js",
|
||||
"build": "tsc",
|
||||
"build:watch": "tsc --watch",
|
||||
"start": "node dist/main.js",
|
||||
"start:prod": "NODE_ENV=production node dist/main.js",
|
||||
|
@ -15,7 +15,6 @@ export interface WebSocketResponse {
|
||||
|
||||
export interface PostMessageble {
|
||||
postMessage(message: any): void;
|
||||
onDidReceiveMessage(callback: MessageHandler): { dispose: () => void };
|
||||
}
|
||||
|
||||
// 监听器回调类型
|
||||
|
@ -108,7 +108,6 @@ wss.on('connection', ws => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const option = getInitConnectionOption();
|
||||
|
||||
// 注册消息接受的管线
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { app, BrowserWindow } from 'electron';
|
||||
import WebSocket from 'ws';
|
||||
import { app, BrowserWindow, ipcMain } from 'electron';
|
||||
import * as OpenMCPService from '../resources/service';
|
||||
import * as path from 'path';
|
||||
import { ElectronIPCLike, getInitConnectionOption, ILaunchSigature, updateConnectionOption } from './util';
|
||||
|
||||
let mainWindow: BrowserWindow
|
||||
|
||||
@ -10,21 +11,15 @@ function createWindow(): void {
|
||||
useContentSize: true,
|
||||
width: 1200,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
nodeIntegration: true,
|
||||
contextIsolation: true,
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
},
|
||||
autoHideMenuBar: true
|
||||
})
|
||||
autoHideMenuBar: true,
|
||||
icon: path.join(__dirname, '..', 'icons', 'icon.png')
|
||||
});
|
||||
|
||||
mainWindow.loadFile('resources/renderer/index.html')
|
||||
}
|
||||
|
||||
const wss = new (WebSocket as any).Server({ port: 8080 });
|
||||
|
||||
wss.on('connection', (ws: any) => {
|
||||
|
||||
// 仿造 webview 进行统一接口访问
|
||||
const webview = new OpenMCPService.VSCodeWebViewLike(ws);
|
||||
const webview = new ElectronIPCLike(mainWindow.webContents);
|
||||
|
||||
// 先发送成功建立的消息
|
||||
webview.postMessage({
|
||||
@ -35,17 +30,58 @@ wss.on('connection', (ws: any) => {
|
||||
}
|
||||
});
|
||||
|
||||
const option = getInitConnectionOption();
|
||||
|
||||
// 注册消息接受的管线
|
||||
webview.onDidReceiveMessage((message: any) => {
|
||||
console.info(`command: [${message.command || 'No Command'}]`);
|
||||
|
||||
const { command, data } = message;
|
||||
OpenMCPService.routeMessage(command, data, webview);
|
||||
|
||||
switch (command) {
|
||||
case 'electron/launch-signature':
|
||||
const launchResultMessage: ILaunchSigature = option.type === 'stdio' ?
|
||||
{
|
||||
type: 'stdio',
|
||||
commandString: option.command + ' ' + option.args.join(' '),
|
||||
cwd: option.cwd || ''
|
||||
} :
|
||||
{
|
||||
type: 'sse',
|
||||
url: option.url,
|
||||
oauth: option.oauth || ''
|
||||
};
|
||||
|
||||
const launchResult = {
|
||||
code: 200,
|
||||
msg: launchResultMessage
|
||||
};
|
||||
|
||||
webview.postMessage({
|
||||
command: 'electron/launch-signature',
|
||||
data: launchResult
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case 'electron/update-connection-sigature':
|
||||
updateConnectionOption(data);
|
||||
break;
|
||||
|
||||
default:
|
||||
OpenMCPService.routeMessage(command, data, webview);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
const indexPath = path.join(__dirname, '..', 'resources/renderer/index.html');
|
||||
mainWindow.loadFile(indexPath);
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
createWindow();
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
|
12
software/src/preload.ts
Normal file
12
software/src/preload.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { contextBridge, ipcRenderer } from 'electron';
|
||||
|
||||
contextBridge.exposeInMainWorld('electronApi', {
|
||||
onReply: (callback: (event: MessageEvent<any>) => void) => {
|
||||
ipcRenderer.on('message', (event, data) => {
|
||||
callback({ data } as MessageEvent<any>);
|
||||
});
|
||||
},
|
||||
sendToMain: (message: any) => {
|
||||
ipcRenderer.send('message', message);
|
||||
}
|
||||
});
|
89
software/src/util.ts
Normal file
89
software/src/util.ts
Normal file
@ -0,0 +1,89 @@
|
||||
|
||||
import { ipcMain } from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
export class ElectronIPCLike {
|
||||
private webContents: Electron.WebContents;
|
||||
|
||||
constructor(webContents: Electron.WebContents) {
|
||||
this.webContents = webContents;
|
||||
}
|
||||
|
||||
postMessage(message: { command: string; data: any }): void {
|
||||
this.webContents.send('message', message);
|
||||
}
|
||||
|
||||
onDidReceiveMessage(callback: (message: { command: string; data: any }) => void): void {
|
||||
ipcMain.on('message', (event, message) => {
|
||||
callback(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface IStdioLaunchSignature {
|
||||
type: 'stdio';
|
||||
commandString: string;
|
||||
cwd: string;
|
||||
}
|
||||
|
||||
interface ISSELaunchSignature {
|
||||
type:'sse';
|
||||
url: string;
|
||||
oauth: string;
|
||||
}
|
||||
|
||||
export type ILaunchSigature = IStdioLaunchSignature | ISSELaunchSignature;
|
||||
|
||||
export function refreshConnectionOption(envPath: string) {
|
||||
const defaultOption = {
|
||||
type:'stdio',
|
||||
command: 'mcp',
|
||||
args: ['run', 'main.py'],
|
||||
cwd: '../server'
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(defaultOption, null, 4));
|
||||
|
||||
return defaultOption;
|
||||
}
|
||||
|
||||
export function getInitConnectionOption() {
|
||||
const envPath = path.join(__dirname, '..', '.env');
|
||||
|
||||
if (!fs.existsSync(envPath)) {
|
||||
return refreshConnectionOption(envPath);
|
||||
}
|
||||
|
||||
try {
|
||||
const option = JSON.parse(fs.readFileSync(envPath, 'utf-8'));
|
||||
return option;
|
||||
|
||||
} catch (error) {
|
||||
return refreshConnectionOption(envPath);
|
||||
}
|
||||
}
|
||||
|
||||
export function updateConnectionOption(data: any) {
|
||||
const envPath = path.join(__dirname, '..', '.env');
|
||||
|
||||
if (data.connectionType === 'STDIO') {
|
||||
const connectionItem = {
|
||||
type: 'stdio',
|
||||
command: data.command,
|
||||
args: data.args,
|
||||
cwd: data.cwd.replace(/\\/g, '/')
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(connectionItem, null, 4));
|
||||
} else {
|
||||
const connectionItem = {
|
||||
type: 'sse',
|
||||
url: data.url,
|
||||
oauth: data.oauth
|
||||
};
|
||||
|
||||
fs.writeFileSync(envPath, JSON.stringify(connectionItem, null, 4));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user