更新插件端架构

This commit is contained in:
锦恢 2025-05-01 03:17:20 +08:00
parent 34936d944d
commit c1b06313d7
16 changed files with 448 additions and 189 deletions

View File

@ -64,6 +64,30 @@
"title": "打开配置",
"category": "openmcp",
"icon": "$(gear)"
},
{
"command": "openmcp.sidebar.installed-connection.deleteConnection",
"title": "删除连接",
"category": "openmcp",
"icon": "$(trash)"
},
{
"command": "openmcp.sidebar.installed-connection.refresh",
"title": "刷新",
"category": "openmcp",
"icon": "$(refresh)"
},
{
"command": "openmcp.sidebar.installed-connection.addConnection",
"title": "添加连接",
"category": "openmcp",
"icon": "$(add)"
},
{
"command": "openmcp.sidebar.installed-connection.openConfiguration",
"title": "打开配置",
"category": "openmcp",
"icon": "$(gear)"
}
],
"menus": {
@ -78,24 +102,39 @@
{
"command": "openmcp.sidebar.workspace-connection.refresh",
"group": "navigation",
"when": "view == openmcp.sidebar-view.workspace-connection"
"when": "view == openmcp.sidebar.workspace-connection"
},
{
"command": "openmcp.sidebar.workspace-connection.addConnection",
"group": "navigation",
"when": "view == openmcp.sidebar-view.workspace-connection"
"when": "view == openmcp.sidebar.workspace-connection"
},
{
"command": "openmcp.sidebar.workspace-connection.openConfiguration",
"group": "navigation",
"when": "view == openmcp.sidebar-view.workspace-connection"
"when": "view == openmcp.sidebar.workspace-connection"
},
{
"command": "openmcp.sidebar.installed-connection.refresh",
"group": "navigation",
"when": "view == openmcp.sidebar.installed-connection"
},
{
"command": "openmcp.sidebar.installed-connection.addConnection",
"group": "navigation",
"when": "view == openmcp.sidebar.installed-connection"
},
{
"command": "openmcp.sidebar.installed-connection.openConfiguration",
"group": "navigation",
"when": "view == openmcp.sidebar.installed-connection"
}
],
"view/item/context": [
{
"command": "openmcp.sidebar.workspace-connection.revealWebviewPanel",
"group": "inline@1",
"when": "view == openmcp.sidebar-view.workspace-connection",
"when": "view == openmcp.sidebar.workspace-connection || view == openmcp.sidebar.installed-connection",
"args": {
"view": "${viewItem}"
}
@ -103,7 +142,15 @@
{
"command": "openmcp.sidebar.workspace-connection.deleteConnection",
"group": "inline@2",
"when": "view == openmcp.sidebar-view.workspace-connection",
"when": "view == openmcp.sidebar.workspace-connection",
"args": {
"view": "${viewItem}"
}
},
{
"command": "openmcp.sidebar.installed-connection.deleteConnection",
"group": "inline@2",
"when": "view == openmcp.sidebar.installed-connection",
"args": {
"view": "${viewItem}"
}
@ -122,11 +169,17 @@
"views": {
"openmcp-sidebar": [
{
"id": "openmcp.sidebar-view.workspace-connection",
"id": "openmcp.sidebar.workspace-connection",
"icon": "./icons/protocol.svg",
"name": "MCP 连接 (工作区)",
"type": "tree"
},
{
"id": "openmcp.sidebar.installed-connection",
"icon": "./icons/protocol.svg",
"name": "安装的 MCP 服务器",
"type": "tree"
},
{
"id": "openmcp.sidebar.help",
"icon": "./icons/protocol.svg",
@ -146,7 +199,7 @@
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.10.2",
"@seald-io/nedb": "^4.1.1",
"@seald-io/nedb": "^4.1.1",
"axios": "^1.7.7",
"bson": "^6.8.0",
"openai": "^4.93.0",

View File

@ -1,22 +1,41 @@
import * as vscode from 'vscode';
import { registerCommands, registerTreeDataProviders } from '.';
import { HelpProvider } from '../sidebar/help.controller';
import { McpWorkspaceConnectProvider } from '../sidebar/workspace.controller';
import { McpInstalledConnectProvider } from '../sidebar/installed.controller';
import { WebviewController } from '../webview/webview.controller';
export const InstallModules = [
McpWorkspaceConnectProvider,
McpInstalledConnectProvider,
HelpProvider,
WebviewController
];
const registerSingles = new Map<string, any>();
export function launch(context: vscode.ExtensionContext) {
for (const [command, value] of registerCommands) {
context.subscriptions.push(vscode.commands.registerCommand(command, (...args: any[]) => {
value.handler(context, ...args);
}));
}
for (const [providerId, value] of registerTreeDataProviders) {
const provider = new value.providerConstructor(context);
registerSingles.set(providerId, provider);
context.subscriptions.push(
vscode.window.registerTreeDataProvider(providerId, value.provider)
vscode.window.registerTreeDataProvider(providerId, provider)
);
}
for (const [command, value] of registerCommands) {
const namespace = value.target.__openmcp_namespace;
const targetCommand = namespace ? `${namespace}.${command}` : command;
const target = registerSingles.has(namespace) ? registerSingles.get(namespace) : value.target;
context.subscriptions.push(vscode.commands.registerCommand(targetCommand, (...args: any[]) => {
target[value.propertyKey](context,...args);
}));
}
}

View File

@ -10,15 +10,17 @@ export interface CustomDescriptor<T> {
}
export interface IRegisterCommandItem {
handler: (context: ExtensionContext, ...args: any[]) => void;
handler: (context: ExtensionContext, ...args: any[]) => any;
options?: any;
target: any;
propertyKey: string;
}
export type CommandHandlerDescriptor = CustomDescriptor<IRegisterCommandItem['handler']>;
export interface IRegisterTreeDataProviderItem<T> {
provider: TreeDataProvider<T>;
providerConstructor: TreeDataProviderConstructor<T>;
options?: any;
}
export type TreeDataProviderDescriptor<T> = CustomDescriptor<IRegisterTreeDataProviderItem<T>['provider']>;
export type TreeDataProviderConstructor<T> = new (context: ExtensionContext, ...args: any[]) => TreeDataProvider<T>;

View File

@ -1,34 +1,32 @@
import { CommandHandlerDescriptor, IRegisterCommandItem, IRegisterTreeDataProviderItem, TreeDataProviderDescriptor } from "./index.dto";
import { CommandHandlerDescriptor, IRegisterCommandItem, IRegisterTreeDataProviderItem, TreeDataProviderConstructor } from "./index.dto";
export const registerCommands = new Map<string, IRegisterCommandItem>();
export const registerCommands = new Array<[string, IRegisterCommandItem]>();
export const registerTreeDataProviders = new Map<string, IRegisterTreeDataProviderItem<any>>();
export function RegisterCommand(command: string, options?: any) {
return function(target: any, propertyKey: string, descriptor: CommandHandlerDescriptor) {
return function (target: any, propertyKey: string, descriptor: CommandHandlerDescriptor) {
const handler = descriptor.value;
// 根据 option 进行的操作
// ...
console.log(propertyKey);
console.log(descriptor);
if (handler) {
registerCommands.set(command, { handler, options });
registerCommands.push([command, { handler, target, propertyKey, options }]);
}
return descriptor;
}
}
export function RegisterTreeDataProvider<T>(command: string, options?: any) {
return function(target: any, propertyKey: string, descriptor: TreeDataProviderDescriptor<T>) {
const provider = descriptor.value;
export function RegisterTreeDataProvider<T>(providerId: string, options?: any) {
return function (target: TreeDataProviderConstructor<T>) {
// 根据 option 进行的操作
// ...
target.prototype.__openmcp_namespace = providerId;
if (provider) {
registerTreeDataProviders.set(command, { provider, options });
}
return descriptor;
registerTreeDataProviders.set(providerId, {
providerConstructor: target,
options
});
}
}

View File

@ -1,10 +1,6 @@
import * as vscode from 'vscode';
import * as OpenMCPService from '../resources/service';
import { getDefaultLanunchSigature, getLaunchCWD, revealOpenMcpWebviewPanel } from './webview';
import { registerSidebar } from './sidebar';
import { getWorkspaceConnectionConfigItemByPath } from './global';
import type { ConnectionViewItem } from './sidebar/common';
import { launch } from './common/entry';
export function activate(context: vscode.ExtensionContext) {
console.log('activate openmcp');
@ -15,49 +11,7 @@ export function activate(context: vscode.ExtensionContext) {
const workspace = workspaceFolder?.uri.fsPath || '';
OpenMCPService.setVscodeWorkspace(workspace);
registerSidebar(context);
context.subscriptions.push(
vscode.commands.registerCommand('openmcp.sidebar.workspace-connection.revealWebviewPanel', (view: ConnectionViewItem) => {
const item = view.item;
revealOpenMcpWebviewPanel(context, item.filePath || item.name, item);
}
));
context.subscriptions.push(
vscode.commands.registerCommand('openmcp.sidebar.workspace-connection.deleteConnection', (view: ConnectionViewItem) => {
deleteConnection(context, view);
}
));
context.subscriptions.push(
vscode.commands.registerCommand('openmcp.showOpenMCP', async (uri: vscode.Uri) => {
const connectionItem = getWorkspaceConnectionConfigItemByPath(uri.fsPath);
if (!connectionItem) {
// 项目不存在连接信息
const cwd = getLaunchCWD(context, uri);
const sigature = getDefaultLanunchSigature(uri.fsPath, cwd);
if (!sigature) {
vscode.window.showErrorMessage('OpenMCP: 无法获取启动参数');
return;
}
revealOpenMcpWebviewPanel(context, uri.fsPath, {
type: 'stdio',
name: 'OpenMCP',
command: sigature.command,
args: sigature.args,
cwd
});
} else {
revealOpenMcpWebviewPanel(context, uri.fsPath, connectionItem);
}
})
);
launch(context);
}

View File

@ -81,17 +81,27 @@ export function getConnectionConfig() {
return connection;
}
/**
* @description {workspace}/.vscode/openmcp_connection.json
* @returns
*/
export function getWorkspaceConnectionConfigPath() {
const workspace = getWorkspacePath();
const configDir = fspath.join(workspace, '.vscode');
const connectionConfig = fspath.join(configDir, CONNECTION_CONFIG_NAME);
return connectionConfig;
}
/**
* @description {workspace}
* @param workspace
*/
export function getWorkspaceConnectionConfig() {
const workspace = getWorkspacePath();
if (_workspaceConnectionConfig) {
return _workspaceConnectionConfig;
}
const workspace = getWorkspacePath();
const configDir = fspath.join(workspace, '.vscode');
const connectionConfig = fspath.join(configDir, CONNECTION_CONFIG_NAME);

View File

@ -1,6 +1,8 @@
import * as vscode from 'vscode';
import { SidebarItem } from './common';
import { RegisterTreeDataProvider } from '../common';
@RegisterTreeDataProvider('openmcp.sidebar.help')
export class HelpProvider implements vscode.TreeDataProvider<SidebarItem> {
constructor(private context: vscode.ExtensionContext) {

View File

@ -1,29 +0,0 @@
import * as vscode from 'vscode';
import { McpWorkspaceConnectProvider } from './workspace@1';
import { HelpProvider } from './help@3';
// 在 registerSidebar 函数中注册 refresh 命令
export function registerSidebar(context: vscode.ExtensionContext) {
const workspaceConnectionProvider = new McpWorkspaceConnectProvider(context);
// 注册 refresh 命令
context.subscriptions.push(
vscode.commands.registerCommand('openmcp.sidebar.workspace-connection.refresh', () => {
workspaceConnectionProvider.refresh();
})
);
// 注册 MCP 连接的 sidebar 视图
context.subscriptions.push(
vscode.window.registerTreeDataProvider('openmcp.sidebar-view.workspace-connection', workspaceConnectionProvider)
);
// 注册 MCP 连接的 sidebar 视图
// 注册 入门与帮助的 sidebar 视图
context.subscriptions.push(
vscode.window.registerTreeDataProvider('openmcp.sidebar.help', new HelpProvider(context))
);
}

View File

@ -0,0 +1,84 @@
import * as vscode from 'vscode';
import { RegisterCommand, RegisterTreeDataProvider } from '../common';
import { getWorkspaceConnectionConfig, getWorkspacePath, panels, saveWorkspaceConnectionConfig } from '../global';
import { ConnectionViewItem } from './common';
@RegisterTreeDataProvider('openmcp.sidebar.installed-connection')
export class McpInstalledConnectProvider implements vscode.TreeDataProvider<ConnectionViewItem> {
private _onDidChangeTreeData: vscode.EventEmitter<ConnectionViewItem | undefined | null | void> = new vscode.EventEmitter<ConnectionViewItem | undefined | null | void>();
readonly onDidChangeTreeData: vscode.Event<ConnectionViewItem | undefined | null | void> = this._onDidChangeTreeData.event;
constructor(private context: vscode.ExtensionContext) {}
// 实现 TreeDataProvider 接口
getTreeItem(element: ConnectionViewItem): vscode.TreeItem {
return element;
}
getChildren(element?: ConnectionViewItem): Thenable<ConnectionViewItem[]> {
// TODO: 读取 configDir 下的所有文件,作为子节点
const connection = getWorkspaceConnectionConfig();
const sidebarItems = connection.items.map((item, index) => {
// 连接的名字
const itemName = `${item.name} (${item.type})`
return new ConnectionViewItem(itemName, vscode.TreeItemCollapsibleState.None, item, 'server');
})
// 返回子节点
return Promise.resolve(sidebarItems);
}
@RegisterCommand('refresh')
public refresh(context: vscode.ExtensionContext): void {
this._onDidChangeTreeData.fire();
}
@RegisterCommand('addConnection')
public async addConnection(context: vscode.ExtensionContext) {
}
@RegisterCommand('openConfiguration')
public async openConfiguration(context: vscode.ExtensionContext, view: ConnectionViewItem) {
const item = view.item;
const uri = vscode.Uri.file(item.filePath || item.name);
vscode.commands.executeCommand('vscode.open', uri);
}
@RegisterCommand('deleteConnection')
public async deleteConnection(context: vscode.ExtensionContext, view: ConnectionViewItem) {
const workspaceConnectionConfig = getWorkspaceConnectionConfig();
const connectionItem = view.item;
// 弹出确认对话框
const confirm = await vscode.window.showWarningMessage(
`确定要删除连接 "${connectionItem.name}" 吗?`,
{ modal: true },
'确定'
);
if (confirm !== '确定') {
return; // 用户取消删除
}
// 从配置中移除该连接项
const index = workspaceConnectionConfig.items.indexOf(connectionItem);
if (index !== -1) {
workspaceConnectionConfig.items.splice(index, 1);
// 保存更新后的配置
const workspacePath = getWorkspacePath();
saveWorkspaceConnectionConfig(workspacePath);
// 刷新侧边栏视图
vscode.commands.executeCommand('openmcp.sidebar.workspace-connection.refresh');
// 如果该连接有对应的webview面板则关闭它
if (panels.has(connectionItem.filePath || connectionItem.name)) {
const panel = panels.get(connectionItem.filePath || connectionItem.name);
panel?.dispose();
}
}
}
}

View File

@ -0,0 +1,75 @@
import * as vscode from 'vscode';
import { RegisterCommand, RegisterTreeDataProvider } from '../common';
import { getWorkspaceConnectionConfig, getWorkspaceConnectionConfigPath, getWorkspacePath, panels, saveWorkspaceConnectionConfig } from '../global';
import { ConnectionViewItem } from './common';
import { revealOpenMcpWebviewPanel } from '../webview/webview.service';
import { acquireUserCustomConnection, deleteUserConnection } from './workspace.service';
@RegisterTreeDataProvider('openmcp.sidebar.workspace-connection')
export class McpWorkspaceConnectProvider implements vscode.TreeDataProvider<ConnectionViewItem> {
private _onDidChangeTreeData: vscode.EventEmitter<ConnectionViewItem | undefined | null | void> = new vscode.EventEmitter<ConnectionViewItem | undefined | null | void>();
readonly onDidChangeTreeData: vscode.Event<ConnectionViewItem | undefined | null | void> = this._onDidChangeTreeData.event;
constructor(private context: vscode.ExtensionContext) { }
// 实现 TreeDataProvider 接口
getTreeItem(element: ConnectionViewItem): vscode.TreeItem {
return element;
}
getChildren(element?: ConnectionViewItem): Thenable<ConnectionViewItem[]> {
// TODO: 读取 configDir 下的所有文件,作为子节点
const connection = getWorkspaceConnectionConfig();
const sidebarItems = connection.items.map((item, index) => {
// 连接的名字
const itemName = `${item.name} (${item.type})`
return new ConnectionViewItem(itemName, vscode.TreeItemCollapsibleState.None, item, 'server');
})
// 返回子节点
return Promise.resolve(sidebarItems);
}
@RegisterCommand('revealWebviewPanel')
public revealWebviewPanel(context: vscode.ExtensionContext, view: ConnectionViewItem) {
const item = view.item;
revealOpenMcpWebviewPanel(context, item.filePath || item.name, item);
}
@RegisterCommand('refresh')
public refresh(context: vscode.ExtensionContext): void {
console.log(this);
this._onDidChangeTreeData.fire();
}
@RegisterCommand('addConnection')
public async addConnection(context: vscode.ExtensionContext) {
const item = await acquireUserCustomConnection();
if (!item) {
return;
}
const workspaceConnectionConfig = getWorkspaceConnectionConfig();
workspaceConnectionConfig.items.push(item);
saveWorkspaceConnectionConfig(getWorkspacePath());
// 刷新侧边栏视图
vscode.commands.executeCommand('openmcp.sidebar.workspace-connection.refresh');
}
@RegisterCommand('openConfiguration')
public async openConfiguration(context: vscode.ExtensionContext, view: ConnectionViewItem) {
const configPath = getWorkspaceConnectionConfigPath();
const uri = vscode.Uri.file(configPath);
vscode.commands.executeCommand('vscode.open', uri);
}
@RegisterCommand('deleteConnection')
public async deleteConnection(context: vscode.ExtensionContext, view: ConnectionViewItem) {
const connectionItem = view.item;
await deleteUserConnection(connectionItem);
}
}

View File

@ -0,0 +1,127 @@
import { getWorkspaceConnectionConfig, getWorkspacePath, IConnectionItem, panels, saveWorkspaceConnectionConfig } from "../global";
import * as vscode from 'vscode';
export async function acquireUserCustomConnection(): Promise<IConnectionItem | undefined> {
// 让用户选择连接类型
const connectionType = await vscode.window.showQuickPick(['stdio', 'sse'], {
placeHolder: '请选择连接类型'
});
if (!connectionType) {
return; // 用户取消选择
}
if (connectionType === 'stdio') {
// 获取 command
const commandString = await vscode.window.showInputBox({
prompt: '请输入连接的 command',
placeHolder: '例如: mcp run main.py'
});
if (!commandString) {
return; // 用户取消输入
}
// 获取 cwd
const cwd = await vscode.window.showInputBox({
prompt: '请输入工作目录 (cwd),可选',
placeHolder: '例如: /path/to/project'
});
// 校验 command + cwd 是否有效
try {
const commandPath = await validateAndGetCommandPath(commandString, cwd);
console.log('Command Path:', commandPath);
} catch (error) {
vscode.window.showErrorMessage(`无效的 command: ${error}`);
return;
}
const commands = commandString.split(' ');
const command = commands[0];
const args = commands.slice(1);
// 保存连接配置
return {
type: 'stdio',
name: `stdio-${Date.now()}`,
command: command,
args,
cwd: cwd || ''
};
} else if (connectionType === 'sse') {
// 获取 url
const url = await vscode.window.showInputBox({
prompt: '请输入连接的 URL',
placeHolder: '例如: https://127.0.0.1:8080'
});
if (!url) {
return; // 用户取消输入
}
// 获取 oauth
const oauth = await vscode.window.showInputBox({
prompt: '请输入 OAuth 令牌,可选',
placeHolder: '例如: your-oauth-token'
});
// 保存连接配置
return {
type: 'sse',
name: `sse-${Date.now()}`,
version: '1.0', // 假设默认版本为 1.0,可根据实际情况修改
url: url,
oauth: oauth || ''
}
}
}
export async function deleteUserConnection(item: IConnectionItem) {
// 弹出确认对话框
const confirm = await vscode.window.showWarningMessage(
`确定要删除连接 "${item.name}" 吗?`,
{ modal: true },
'确定'
);
if (confirm !== '确定') {
return; // 用户取消删除
}
const workspaceConnectionConfig = getWorkspaceConnectionConfig();
// 从配置中移除该连接项
const index = workspaceConnectionConfig.items.indexOf(item);
if (index !== -1) {
workspaceConnectionConfig.items.splice(index, 1);
// 保存更新后的配置
const workspacePath = getWorkspacePath();
saveWorkspaceConnectionConfig(workspacePath);
// 刷新侧边栏视图
vscode.commands.executeCommand('openmcp.sidebar.workspace-connection.refresh');
panels.delete(item.name);
// 如果该连接有对应的webview面板则关闭它
if (panels.has(item.filePath || item.name)) {
const panel = panels.get(item.filePath || item.name);
panel?.dispose();
}
}
}
export async function validateAndGetCommandPath(command: string, cwd?: string): Promise<string> {
const { exec } = require('child_process');
const { promisify } = require('util');
const execAsync = promisify(exec);
try {
const { stdout } = await execAsync(`which ${command.split(' ')[0]}`, { cwd });
return stdout.trim();
} catch (error) {
throw new Error(`无法找到命令: ${command.split(' ')[0]}`);
}
}

View File

@ -1,69 +0,0 @@
import * as vscode from 'vscode';
import { ConnectionViewItem } from './common';
import { getWorkspaceConnectionConfig, getWorkspacePath, panels, saveWorkspaceConnectionConfig } from '../global';
export class McpWorkspaceConnectProvider implements vscode.TreeDataProvider<ConnectionViewItem> {
private _onDidChangeTreeData: vscode.EventEmitter<ConnectionViewItem | undefined | null | void> = new vscode.EventEmitter<ConnectionViewItem | undefined | null | void>();
readonly onDidChangeTreeData: vscode.Event<ConnectionViewItem | undefined | null | void> = this._onDidChangeTreeData.event;
constructor(private context: vscode.ExtensionContext) {
}
// 实现 TreeDataProvider 接口
getTreeItem(element: ConnectionViewItem): vscode.TreeItem {
return element;
}
getChildren(element?: ConnectionViewItem): Thenable<ConnectionViewItem[]> {
// TODO: 读取 configDir 下的所有文件,作为子节点
const connection = getWorkspaceConnectionConfig();
const sidebarItems = connection.items.map((item, index) => {
// 连接的名字
const itemName = `${item.name} (${item.type})`
return new ConnectionViewItem(itemName, vscode.TreeItemCollapsibleState.None, item, 'server');
})
// 返回子节点
return Promise.resolve(sidebarItems);
}
// 添加 refresh 方法
public refresh(): void {
this._onDidChangeTreeData.fire();
}
}
export async function deleteConnection(context: vscode.ExtensionContext, view: ConnectionViewItem) {
const workspaceConnectionConfig = getWorkspaceConnectionConfig();
const connectionItem = view.item;
// 弹出确认对话框
const confirm = await vscode.window.showWarningMessage(
`确定要删除连接 "${connectionItem.name}" 吗?`,
{ modal: true },
'确定'
);
if (confirm !== '确定') {
return; // 用户取消删除
}
// 从配置中移除该连接项
const index = workspaceConnectionConfig.items.indexOf(connectionItem);
if (index !== -1) {
workspaceConnectionConfig.items.splice(index, 1);
// 保存更新后的配置
const workspacePath = getWorkspacePath();
saveWorkspaceConnectionConfig(workspacePath);
// 刷新侧边栏视图
vscode.commands.executeCommand('openmcp.sidebar.workspace-connection.refresh');
// 如果该连接有对应的webview面板则关闭它
if (panels.has(connectionItem.filePath || connectionItem.name)) {
const panel = panels.get(connectionItem.filePath || connectionItem.name);
panel?.dispose();
}
}
}

View File

@ -0,0 +1,33 @@
import * as vscode from 'vscode';
import { RegisterCommand } from "../common";
import { getDefaultLanunchSignature, getLaunchCWD, revealOpenMcpWebviewPanel } from './webview.service';
import { getWorkspaceConnectionConfigItemByPath } from '../global';
export class WebviewController {
@RegisterCommand('openmcp.showOpenMCP')
async showOpenMCP(context: vscode.ExtensionContext, uri: vscode.Uri) {
const connectionItem = getWorkspaceConnectionConfigItemByPath(uri.fsPath);
if (!connectionItem) {
// 项目不存在连接信息
const cwd = getLaunchCWD(context, uri);
const sigature = getDefaultLanunchSignature(uri.fsPath, cwd);
if (!sigature) {
vscode.window.showErrorMessage('OpenMCP: 无法获取启动参数');
return;
}
revealOpenMcpWebviewPanel(context, uri.fsPath, {
type: 'stdio',
name: 'OpenMCP',
command: sigature.command,
args: sigature.args,
cwd
});
} else {
revealOpenMcpWebviewPanel(context, uri.fsPath, connectionItem);
}
}
}

View File

@ -1,9 +1,8 @@
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as fspath from 'path';
import { getWorkspaceConnectionConfig, getWorkspacePath, IConnectionItem, ILaunchSigature, panels, saveWorkspaceConnectionConfig, updateWorkspaceConnectionConfig } from './global';
import * as OpenMCPService from '../resources/service';
import { IConnectionItem, ILaunchSigature, panels, updateWorkspaceConnectionConfig } from '../global';
import * as OpenMCPService from '../../resources/service';
export function getWebviewContent(context: vscode.ExtensionContext, panel: vscode.WebviewPanel): string | undefined {
const viewRoot = fspath.join(context.extensionPath, 'resources', 'renderer');
@ -114,7 +113,7 @@ export function revealOpenMcpWebviewPanel(
return panel;
}
export function getDefaultLanunchSigature(path: string, cwd: string) {
export function getDefaultLanunchSignature(path: string, cwd: string) {
const relativePath = fspath.relative(cwd, path);
if (relativePath.endsWith('.py')) {

View File

@ -8,6 +8,7 @@
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
// 访 resources
"paths": {
"@resources/*": ["./resources/*"]