支持其他语言

This commit is contained in:
锦恢 2025-06-09 17:54:50 +08:00
parent fb092c8ad6
commit 3ceb5a7b06
23 changed files with 385 additions and 80 deletions

View File

@ -11,9 +11,6 @@
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off",
"i18n-haru.root": "renderer/src/i18n",
"i18n-haru.main": "zh",
"i18n-ally.localesPaths": [
"renderer/src/i18n"
]
"i18n-haru.root": "l10n",
"i18n-haru.main": "zh"
}

View File

@ -7,6 +7,7 @@
- 调试结果的工作区从 .vscode 迁移到 .openmcp连接配置文件从 .vscode/openmcp_connection.json 迁移到 .openmcp/connection.json
- 技术栈更新openmcp 全链路组件切换为 esm
- 优化引导界面文字布局。
- 文档和软件本体支持其他国家语言。
## [main] 0.1.4
- 重新实现 openai 协议的底层网络实现,从而支持 Google Gemini 全系列模型。

View File

@ -12,8 +12,6 @@
</div>
## OpenMCP
一款用于 MCP 服务端调试的一体化 vscode/trae/cursor 插件。

17
l10n/bundle.l10n.en.json Normal file
View File

@ -0,0 +1,17 @@
{
"ensure-delete-connection": "Are you sure you want to delete connection {0}?",
"confirm": "OK",
"choose-connection-type": "Please select the connection type",
"please-enter-connection-command": "Please enter the connection command",
"example-mcp-run": "For example: mcp run main.py",
"please-enter-cwd": "Please enter the working directory (cwd), optional",
"please-enter-cwd-placeholder": "For example: /path/to/project",
"please-enter-url": "Please enter the connection URL",
"example-as": "For example:",
"enter-optional-oauth": "Please enter the OAuth token, optional",
"quick-start": "Getting Started",
"read-document": "Read documentation",
"report-issue": "Report a problem",
"join-project": "Participate in the project",
"comment-plugin": "Comment Plugin"
}

17
l10n/bundle.l10n.ja.json Normal file
View File

@ -0,0 +1,17 @@
{
"ensure-delete-connection": "接続 {0} を削除してもよろしいですか?",
"confirm": "確定",
"choose-connection-type": "接続タイプを選択してください",
"please-enter-connection-command": "接続コマンドを入力してください",
"example-mcp-run": "例: mcp run main.py",
"please-enter-cwd": "作業ディレクトリ (cwd) を入力してください (オプション)",
"please-enter-cwd-placeholder": "例: /path/to/project",
"please-enter-url": "接続URLを入力してください",
"example-as": "例えば:",
"enter-optional-oauth": "OAuthトークンを入力してください任意",
"quick-start": "はじめに",
"read-document": "ドキュメントを読む",
"report-issue": "問題を報告",
"join-project": "プロジェクトに参加する",
"comment-plugin": "コメントプラグイン"
}

View File

@ -0,0 +1,17 @@
{
"ensure-delete-connection": "确定要删除连接 {0} 吗?",
"confirm": "确定",
"choose-connection-type": "请选择连接类型",
"please-enter-connection-command": "请输入连接的 command",
"example-mcp-run": "例如: mcp run main.py",
"please-enter-cwd": "请输入工作目录 (cwd),可选",
"please-enter-cwd-placeholder": "例如: /path/to/project",
"please-enter-url": "请输入连接的 URL",
"example-as": "例如:",
"enter-optional-oauth": "请输入 OAuth 令牌,可选",
"quick-start": "入门",
"read-document": "阅读文档",
"report-issue": "报告问题",
"join-project": "参与项目",
"comment-plugin": "评论插件"
}

View File

@ -22,10 +22,13 @@
"main": "./dist/extension.js",
"icon": "icons/openmcp.png",
"contributes": {
"configuration": {
"properties": {}
},
"commands": [
{
"command": "openmcp.showOpenMCP",
"title": "展示 OpenMCP",
"title": "%openmcp.showOpenMCP.title%",
"category": "openmcp",
"icon": {
"light": "./icons/light/protocol.svg",
@ -34,7 +37,7 @@
},
{
"command": "openmcp.sidebar.workspace-connection.revealWebviewPanel",
"title": "连接",
"title": "%openmcp.sidebar.workspace-connection.revealWebviewPanel.title%",
"category": "openmcp",
"icon": {
"light": "./icons/light/protocol.svg",
@ -43,31 +46,31 @@
},
{
"command": "openmcp.sidebar.workspace-connection.deleteConnection",
"title": "删除连接",
"title": "%openmcp.sidebar.workspace-connection.deleteConnection.title%",
"category": "openmcp",
"icon": "$(trash)"
},
{
"command": "openmcp.sidebar.workspace-connection.refresh",
"title": "刷新",
"title": "%openmcp.sidebar.workspace-connection.refresh.title%",
"category": "openmcp",
"icon": "$(refresh)"
},
{
"command": "openmcp.sidebar.workspace-connection.addConnection",
"title": "添加连接",
"title": "%openmcp.sidebar.workspace-connection.addConnection.title%",
"category": "openmcp",
"icon": "$(add)"
},
{
"command": "openmcp.sidebar.workspace-connection.openConfiguration",
"title": "打开配置",
"title": "%openmcp.sidebar.workspace-connection.openConfiguration.title%",
"category": "openmcp",
"icon": "$(gear)"
},
{
"command": "openmcp.sidebar.installed-connection.revealWebviewPanel",
"title": "连接",
"title": "%openmcp.sidebar.installed-connection.revealWebviewPanel.title%",
"category": "openmcp",
"icon": {
"light": "./icons/light/protocol.svg",
@ -76,31 +79,31 @@
},
{
"command": "openmcp.sidebar.installed-connection.deleteConnection",
"title": "删除连接",
"title": "%openmcp.sidebar.installed-connection.deleteConnection.title%",
"category": "openmcp",
"icon": "$(trash)"
},
{
"command": "openmcp.sidebar.installed-connection.refresh",
"title": "刷新",
"title": "%openmcp.sidebar.installed-connection.refresh.title%",
"category": "openmcp",
"icon": "$(refresh)"
},
{
"command": "openmcp.sidebar.installed-connection.addConnection",
"title": "添加连接",
"title": "%openmcp.sidebar.installed-connection.addConnection.title%",
"category": "openmcp",
"icon": "$(add)"
},
{
"command": "openmcp.sidebar.installed-connection.openConfiguration",
"title": "打开配置",
"title": "%openmcp.sidebar.installed-connection.openConfiguration.title%",
"category": "openmcp",
"icon": "$(gear)"
},
{
"command": "openmcp.hook.test-ocr",
"title": "测试 OCR",
"title": "%openmcp.hook.test-ocr.title%",
"category": "openmcp",
"icon": "$(test)"
}
@ -194,19 +197,19 @@
{
"id": "openmcp.sidebar.workspace-connection",
"icon": "./icons/protocol.svg",
"name": "MCP 连接 (工作区)",
"name": "%openmcp.sidebar.workspace-connection.view.title%",
"type": "tree"
},
{
"id": "openmcp.sidebar.installed-connection",
"icon": "./icons/protocol.svg",
"name": "安装的 MCP 服务器",
"name": "%openmcp.sidebar.installed-connection.view.title%",
"type": "tree"
},
{
"id": "openmcp.sidebar.help",
"icon": "./icons/protocol.svg",
"name": "入门与帮助",
"name": "%openmcp.sidebar.help.view.title%",
"type": "tree"
}
]
@ -265,4 +268,4 @@
"webpack-cli": "^5.1.4"
},
"packageManager": "npm@10.0.0"
}
}

17
package.nls.ja.json Normal file
View File

@ -0,0 +1,17 @@
{
"openmcp.showOpenMCP.title": "OpenMCP を表示",
"openmcp.sidebar.workspace-connection.revealWebviewPanel.title": "接続",
"openmcp.sidebar.workspace-connection.deleteConnection.title": "接続を削除",
"openmcp.sidebar.workspace-connection.refresh.title": "更新",
"openmcp.sidebar.workspace-connection.addConnection.title": "接続を追加",
"openmcp.sidebar.workspace-connection.openConfiguration.title": "設定を開く",
"openmcp.sidebar.installed-connection.revealWebviewPanel.title": "接続",
"openmcp.sidebar.installed-connection.deleteConnection.title": "接続を削除",
"openmcp.sidebar.installed-connection.refresh.title": "更新",
"openmcp.sidebar.installed-connection.addConnection.title": "接続を追加",
"openmcp.sidebar.installed-connection.openConfiguration.title": "設定を開く",
"openmcp.hook.test-ocr.title": "OCR をテスト",
"openmcp.sidebar.workspace-connection.view.title": "MCP 接続(ワークスペース)",
"openmcp.sidebar.installed-connection.view.title": "インストール済み MCP サーバー",
"openmcp.sidebar.help.view.title": "はじめに・ヘルプ"
}

17
package.nls.json Normal file
View File

@ -0,0 +1,17 @@
{
"openmcp.showOpenMCP.title": "Show OpenMCP",
"openmcp.sidebar.workspace-connection.revealWebviewPanel.title": "Connect",
"openmcp.sidebar.workspace-connection.deleteConnection.title": "Delete Connection",
"openmcp.sidebar.workspace-connection.refresh.title": "Refresh",
"openmcp.sidebar.workspace-connection.addConnection.title": "Add Connection",
"openmcp.sidebar.workspace-connection.openConfiguration.title": "Open Configuration",
"openmcp.sidebar.installed-connection.revealWebviewPanel.title": "Connect",
"openmcp.sidebar.installed-connection.deleteConnection.title": "Delete Connection",
"openmcp.sidebar.installed-connection.refresh.title": "Refresh",
"openmcp.sidebar.installed-connection.addConnection.title": "Add Connection",
"openmcp.sidebar.installed-connection.openConfiguration.title": "Open Configuration",
"openmcp.hook.test-ocr.title": "Test OCR",
"openmcp.sidebar.workspace-connection.view.title": "MCP Connections (Workspace)",
"openmcp.sidebar.installed-connection.view.title": "Installed MCP Servers",
"openmcp.sidebar.help.view.title": "Getting Started & Help"
}

17
package.nls.zh-cn.json Normal file
View File

@ -0,0 +1,17 @@
{
"openmcp.showOpenMCP.title": "展示 OpenMCP",
"openmcp.sidebar.workspace-connection.revealWebviewPanel.title": "连接",
"openmcp.sidebar.workspace-connection.deleteConnection.title": "删除连接",
"openmcp.sidebar.workspace-connection.refresh.title": "刷新",
"openmcp.sidebar.workspace-connection.addConnection.title": "添加连接",
"openmcp.sidebar.workspace-connection.openConfiguration.title": "打开配置",
"openmcp.sidebar.installed-connection.revealWebviewPanel.title": "连接",
"openmcp.sidebar.installed-connection.deleteConnection.title": "删除连接",
"openmcp.sidebar.installed-connection.refresh.title": "刷新",
"openmcp.sidebar.installed-connection.addConnection.title": "添加连接",
"openmcp.sidebar.installed-connection.openConfiguration.title": "打开配置",
"openmcp.hook.test-ocr.title": "测试 OCR",
"openmcp.sidebar.workspace-connection.view.title": "MCP 连接 (工作区)",
"openmcp.sidebar.installed-connection.view.title": "安装的 MCP 服务器",
"openmcp.sidebar.help.view.title": "入门与帮助"
}

View File

@ -158,5 +158,19 @@
"waiting-mcp-server": "في انتظار استجابة خادم MCP",
"parallel-tool-calls": "السماح للنموذج باستدعاء أدوات متعددة في رد واحد",
"proxy-server": "خادم وكيل",
"update-model-list": "تحديث قائمة النماذج"
"update-model-list": "تحديث قائمة النماذج",
"ensure-delete-connection": "هل أنت متأكد أنك تريد حذف الاتصال $1؟",
"choose-connection-type": "الرجاء اختيار نوع الاتصال",
"please-enter-connection-command": "الرجاء إدخال أمر الاتصال",
"example-mcp-run": "على سبيل المثال: mcp run main.py",
"please-enter-cwd": "الرجاء إدخال دليل العمل (cwd)، اختياري",
"please-enter-cwd-placeholder": "على سبيل المثال: /path/to/project",
"please-enter-url": "الرجاء إدخال عنوان URL للاتصال",
"example-as": "على سبيل المثال:",
"enter-optional-oauth": "الرجاء إدخال رمز OAuth، اختياري",
"quick-start": "مقدمة",
"read-document": "قراءة الوثائق",
"report-issue": "الإبلاغ عن مشكلة",
"join-project": "المشاركة في المشروع",
"comment-plugin": "ملحق التعليقات"
}

View File

@ -158,5 +158,19 @@
"waiting-mcp-server": "Warten auf Antwort vom MCP-Server",
"parallel-tool-calls": "Erlauben Sie dem Modell, mehrere Tools in einer einzigen Antwort aufzurufen",
"proxy-server": "Proxy-Server",
"update-model-list": "Modellliste aktualisieren"
"update-model-list": "Modellliste aktualisieren",
"ensure-delete-connection": "Möchten Sie die Verbindung $1 wirklich löschen?",
"choose-connection-type": "Bitte wählen Sie den Verbindungstyp",
"please-enter-connection-command": "Bitte geben Sie den Verbindungsbefehl ein",
"example-mcp-run": "Beispiel: mcp run main.py",
"please-enter-cwd": "Bitte geben Sie das Arbeitsverzeichnis (cwd) ein, optional",
"please-enter-cwd-placeholder": "Zum Beispiel: /path/to/project",
"please-enter-url": "Bitte geben Sie die Verbindungs-URL ein",
"example-as": "Zum Beispiel:",
"enter-optional-oauth": "Bitte geben Sie das OAuth-Token ein, optional",
"quick-start": "Einführung",
"read-document": "Dokumentation lesen",
"report-issue": "Problem melden",
"join-project": "Am Projekt teilnehmen",
"comment-plugin": "Kommentar-Plugin"
}

View File

@ -158,5 +158,19 @@
"waiting-mcp-server": "En attente de la réponse du serveur MCP",
"parallel-tool-calls": "Permettre au modèle d'appeler plusieurs outils en une seule réponse",
"proxy-server": "Serveur proxy",
"update-model-list": "Mettre à jour la liste des modèles"
"update-model-list": "Mettre à jour la liste des modèles",
"ensure-delete-connection": "Êtes-vous sûr de vouloir supprimer la connexion $1 ?",
"choose-connection-type": "Veuillez sélectionner le type de connexion",
"please-enter-connection-command": "Veuillez saisir la commande de connexion",
"example-mcp-run": "Par exemple : mcp run main.py",
"please-enter-cwd": "Veuillez entrer le répertoire de travail (cwd), facultatif",
"please-enter-cwd-placeholder": "Par exemple : /path/to/project",
"please-enter-url": "Veuillez saisir l'URL de connexion",
"example-as": "Par exemple :",
"enter-optional-oauth": "Veuillez entrer le jeton OAuth, facultatif",
"quick-start": "Premiers pas",
"read-document": "Lire la documentation",
"report-issue": "Signaler un problème",
"join-project": "Participer au projet",
"comment-plugin": "Plugin de commentaires"
}

View File

@ -158,5 +158,19 @@
"waiting-mcp-server": "MCP 서버 응답 대기 중",
"parallel-tool-calls": "모델이 단일 응답에서 여러 도구를 호출할 수 있도록 허용",
"proxy-server": "프록시 서버",
"update-model-list": "모델 목록 업데이트"
"update-model-list": "모델 목록 업데이트",
"ensure-delete-connection": "연결 $1을(를) 삭제하시겠습니까?",
"choose-connection-type": "연결 유형을 선택해 주세요",
"please-enter-connection-command": "연결 명령을 입력해 주세요",
"example-mcp-run": "예: mcp run main.py",
"please-enter-cwd": "작업 디렉토리 (cwd)를 입력하세요 (선택 사항)",
"please-enter-cwd-placeholder": "예: /path/to/project",
"please-enter-url": "연결 URL을 입력해 주세요",
"example-as": "예를 들어:",
"enter-optional-oauth": "OAuth 토큰을 입력하세요 (선택 사항)",
"quick-start": "시작하기",
"read-document": "문서 읽기",
"report-issue": "문제 신고",
"join-project": "프로젝트 참여",
"comment-plugin": "댓글 플러그인"
}

View File

@ -158,5 +158,19 @@
"waiting-mcp-server": "Ожидание ответа от сервера MCP",
"parallel-tool-calls": "Разрешить модели вызывать несколько инструментов в одном ответе",
"proxy-server": "Прокси-сервер",
"update-model-list": "Обновить список моделей"
"update-model-list": "Обновить список моделей",
"ensure-delete-connection": "Вы уверены, что хотите удалить соединение $1?",
"choose-connection-type": "Пожалуйста, выберите тип подключения",
"please-enter-connection-command": "Пожалуйста, введите команду подключения",
"example-mcp-run": "Например: mcp run main.py",
"please-enter-cwd": "Пожалуйста, введите рабочий каталог (cwd), необязательно",
"please-enter-cwd-placeholder": "Например: /path/to/project",
"please-enter-url": "Пожалуйста, введите URL-адрес подключения",
"example-as": "Например:",
"enter-optional-oauth": "Пожалуйста, введите токен OAuth, необязательно",
"quick-start": "Начало работы",
"read-document": "Читать документацию",
"report-issue": "Сообщить о проблеме",
"join-project": "Участвовать в проекте",
"comment-plugin": "Плагин комментариев"
}

View File

@ -158,5 +158,19 @@
"waiting-mcp-server": "等待MCP伺服器響應",
"parallel-tool-calls": "允許模型在單輪回覆中調用多個工具",
"proxy-server": "代理伺服器",
"update-model-list": "更新模型列表"
"update-model-list": "更新模型列表",
"ensure-delete-connection": "確定要刪除連接 $1 嗎?",
"choose-connection-type": "請選擇連接類型",
"please-enter-connection-command": "請輸入連接命令",
"example-mcp-run": "例如: mcp run main.py",
"please-enter-cwd": "請輸入工作目錄 (cwd),可選",
"please-enter-cwd-placeholder": "例如: /path/to/project",
"please-enter-url": "請輸入連接的 URL",
"example-as": "例如:",
"enter-optional-oauth": "請輸入 OAuth 令牌,可選",
"quick-start": "入門",
"read-document": "閱讀文件",
"report-issue": "報告問題",
"join-project": "參與專案",
"comment-plugin": "評論插件"
}

View File

@ -0,0 +1,87 @@
from typing import List
import sys
import os
sys.path.append(os.path.abspath('.'))
import json
from typing import Any
PACKAGE_FILE = './package.json'
LANG_PACKGE_FILES = {
'en': './package.nls.json',
'zh-cn': './package.nls.zh-cn.json',
'ja': './package.nls.ja.json'
}
def read_json(path: str) -> Any:
if not os.path.exists(path):
return {}
try:
with open(path, 'r', encoding='utf-8') as fp:
config = json.load(fp=fp)
return config
except Exception as e:
return {}
def write_json(path: str, obj: object):
with open(path, 'w', encoding='utf-8') as fp:
json.dump(obj, fp=fp, indent=4, ensure_ascii=False)
def generate_title_token(command_name: str) -> str:
names = command_name.split('.')
prj_name = names[0]
main_names = names[1:]
title_token_name = [prj_name] + main_names + ['title']
return '.'.join(title_token_name)
def merge_tokens(lang_package_path: str, tokens: List[str], token_values: List[str]):
config = read_json(lang_package_path)
for token, value in zip(tokens, token_values):
if token not in config:
config[token] = value
write_json(lang_package_path, config)
if __name__ == '__main__':
# adjust main package
config = read_json(PACKAGE_FILE)
token_names = []
token_values = []
# 获取 properties 中的 title
for property_name in config.get('contributes', {}).get('configuration', {}).get('properties', {}):
# property_name: digital-ide.welcome.show
property_body = config['contributes']['configuration']['properties'][property_name]
print(property_body)
token_name = generate_title_token(property_name)
token_names.append(token_name)
if 'description' in property_body and not property_body['description'].startswith('%'):
token_values.append(property_body['description'])
else:
token_values.append("")
property_body['description'] = '%' + token_name + '%'
# 获取 command 中的 title
for item in config.get('contributes', {}).get('commands', []):
if 'command' in item:
token_name = generate_title_token(item['command'])
token_names.append(token_name)
token_values.append(item.get('title', ''))
item['title'] = '%' + token_name + '%'
# 获取 command 中的 title
for viewName in config.get('contributes', {}).get('views', {}):
view = config['contributes']['views'][viewName]
for item in view:
if 'id' in item:
token_name = generate_title_token(item['id'] + '.view')
token_names.append(token_name)
token_values.append(item.get('name', ''))
item['name'] = '%' + token_name + '%'
write_json(PACKAGE_FILE, config)
# cover in lang package
for name, lang_path in LANG_PACKGE_FILES.items():
merge_tokens(lang_path, token_names, token_values)

View File

@ -1,6 +1,7 @@
import * as vscode from 'vscode';
import { setRunningCWD, setVscodeWorkspace } from '../openmcp-sdk/service';
import { launch } from './common/entry';
import { initialiseI18n } from './i18n';
export function activate(context: vscode.ExtensionContext) {
console.log('activate openmcp');
@ -12,6 +13,7 @@ export function activate(context: vscode.ExtensionContext) {
setVscodeWorkspace(workspace);
setRunningCWD(context.extensionPath);
initialiseI18n(context);
launch(context);
}

26
src/i18n/index.ts Normal file
View File

@ -0,0 +1,26 @@
import * as vscode from 'vscode';
import * as fs from 'fs';
const defaultBundle: Record<string, string> = {}
export function initialiseI18n(context: vscode.ExtensionContext) {
if (vscode.l10n.bundle === undefined) {
const bundlePath = context.asAbsolutePath('l10n/bundle.l10n.en.json');
const bundle = JSON.parse(fs.readFileSync(bundlePath, { encoding: 'utf-8' })) as Record<string, string>;
Object.assign(defaultBundle, bundle);
}
}
export function t(message: string, ...args: string[]): string {
if (vscode.l10n.bundle === undefined) {
let translateMessage = defaultBundle[message] || message;
for (let i = 0; i < args.length; ++ i) {
translateMessage = translateMessage.replace(`{${i}}`, args[i]);
}
return translateMessage;
} else {
return vscode.l10n.t(message, ...args);
}
}

View File

@ -1,6 +1,7 @@
import * as vscode from 'vscode';
import { SidebarItem } from './common';
import { RegisterTreeDataProvider } from '../common';
import { t } from '../i18n';
@RegisterTreeDataProvider('openmcp.sidebar.help')
export class HelpProvider implements vscode.TreeDataProvider<SidebarItem> {
@ -16,27 +17,27 @@ export class HelpProvider implements vscode.TreeDataProvider<SidebarItem> {
getChildren(element?: SidebarItem): Thenable<SidebarItem[]> {
// 返回子节点
return Promise.resolve([
new SidebarItem('入门', vscode.TreeItemCollapsibleState.None, {
new SidebarItem(t('quick-start'), vscode.TreeItemCollapsibleState.None, {
command: 'vscode.open',
title: 'Open Guide',
arguments: [vscode.Uri.parse('https://kirigaya.cn/openmcp/plugin-tutorial/usage/connect-mcp.html·')]
}, 'book'),
new SidebarItem('阅读文档', vscode.TreeItemCollapsibleState.None, {
new SidebarItem(t('read-document'), vscode.TreeItemCollapsibleState.None, {
command: 'vscode.open',
title: 'Open Documentation',
arguments: [vscode.Uri.parse('https://kirigaya.cn/openmcp')]
}, 'file-text'),
new SidebarItem('报告问题', vscode.TreeItemCollapsibleState.None, {
new SidebarItem(t('report-issue'), vscode.TreeItemCollapsibleState.None, {
command: 'vscode.open',
title: 'Report Issue',
arguments: [vscode.Uri.parse('https://github.com/LSTM-Kirigaya/openmcp-client/issues')]
}, 'bug'),
new SidebarItem('参与项目', vscode.TreeItemCollapsibleState.None, {
new SidebarItem(t('join-project'), vscode.TreeItemCollapsibleState.None, {
command: 'vscode.open',
title: 'Join Project',
arguments: [vscode.Uri.parse('https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD')]
}, 'organization'),
new SidebarItem('评论插件', vscode.TreeItemCollapsibleState.None, {
new SidebarItem(t('comment-plugin'), vscode.TreeItemCollapsibleState.None, {
command: 'vscode.open',
title: 'Review Extension',
arguments: [vscode.Uri.parse('https://marketplace.visualstudio.com/items?itemName=kirigaya.openmcp&ssr=false#review-details')]

View File

@ -1,21 +1,26 @@
import { getConnectionConfig, panels, saveConnectionConfig, getFirstValidPathFromCommand, McpOptions } from "../global";
import { exec, spawn } from 'node:child_process';
import * as vscode from 'vscode';
import { t } from "../i18n";
export async function deleteInstalledConnection(item: McpOptions[] | McpOptions) {
// 弹出确认对话框
const masterNode = Array.isArray(item) ? item[0] : item;
const name = masterNode.name;
const confirm = await vscode.window.showWarningMessage(
`确定要删除连接 "${name}" 吗?`,
const name = masterNode.name || 'unknown node name';
const res = await vscode.window.showWarningMessage(
t("ensure-delete-connection", name),
{ modal: true },
'确定'
{ title: t('confirm'), value: true },
);
if (confirm !== '确定') {
const confirm = res?.value;
if (!confirm) {
return; // 用户取消删除
}
const installedConnection = getConnectionConfig();
// 从配置中移除该连接项
@ -50,14 +55,14 @@ export async function validateAndGetCommandPath(commandString: string, cwd?: str
return '';
} catch (error) {
console.log(error);
throw new Error(`无法找到命令: ${commandString.split(' ')[0]}`);
throw new Error(`Cannot find command: ${commandString.split(' ')[0]}`);
}
}
export async function acquireInstalledConnection(): Promise<McpOptions[]> {
// 让用户选择连接类型
const connectionType = await vscode.window.showQuickPick(['STDIO', 'SSE', 'STREAMABLE_HTTP'], {
placeHolder: '请选择连接类型',
placeHolder: t('choose-connection-type'),
canPickMany: false,
ignoreFocusOut: true,
});
@ -69,8 +74,8 @@ export async function acquireInstalledConnection(): Promise<McpOptions[]> {
if (connectionType === 'STDIO') {
// 获取 command
const commandString = await vscode.window.showInputBox({
prompt: '请输入连接的 command',
placeHolder: '例如: mcp run main.py'
prompt: t('please-enter-connection-command'),
placeHolder: t('example-mcp-run')
});
if (!commandString) {
@ -79,8 +84,8 @@ export async function acquireInstalledConnection(): Promise<McpOptions[]> {
// 获取 cwd
const cwd = await vscode.window.showInputBox({
prompt: '请输入工作目录 (cwd),可选',
placeHolder: '例如: /path/to/project'
prompt: t('please-enter-cwd'),
placeHolder: t('please-enter-cwd-placeholder')
});
// 校验 command + cwd 是否有效
@ -88,7 +93,7 @@ export async function acquireInstalledConnection(): Promise<McpOptions[]> {
const commandPath = await validateAndGetCommandPath(commandString, cwd);
console.log('Command Path:', commandPath);
} catch (error) {
vscode.window.showErrorMessage(`无效的 command: ${error}`);
vscode.window.showErrorMessage(`Invalid command: ${error}`);
return [];
}
@ -113,8 +118,8 @@ export async function acquireInstalledConnection(): Promise<McpOptions[]> {
} else if (connectionType === 'SSE') {
// 获取 url
const url = await vscode.window.showInputBox({
prompt: '请输入连接的 URL',
placeHolder: '例如: https://127.0.0.1:8282/sse'
prompt: t('please-enter-url'),
placeHolder: t('example-as') + 'https://127.0.0.1:8282/sse'
});
if (!url) {
@ -123,8 +128,8 @@ export async function acquireInstalledConnection(): Promise<McpOptions[]> {
// 获取 oauth
const oauth = await vscode.window.showInputBox({
prompt: '请输入 OAuth 令牌,可选',
placeHolder: '例如: your-oauth-token'
prompt: t('enter-optional-oauth'),
placeHolder: t('example-as') + ' your-oauth-token'
});
// 保存连接配置
@ -138,8 +143,8 @@ export async function acquireInstalledConnection(): Promise<McpOptions[]> {
} else if (connectionType === 'STREAMABLE_HTTP') {
// 获取 url
const url = await vscode.window.showInputBox({
prompt: '请输入连接的 URL',
placeHolder: '例如: https://127.0.0.1:8282/stream'
prompt: t('please-enter-url'),
placeHolder: t('example-as') + ' https://127.0.0.1:8282/stream'
});
if (!url) {
@ -148,8 +153,8 @@ export async function acquireInstalledConnection(): Promise<McpOptions[]> {
// 获取 oauth
const oauth = await vscode.window.showInputBox({
prompt: '请输入 OAuth 令牌,可选',
placeHolder: '例如: your-oauth-token'
prompt: t('enter-optional-oauth'),
placeHolder: t('example-as') + ' your-oauth-token'
});
// 保存连接配置

View File

@ -1,28 +1,28 @@
import { getFirstValidPathFromCommand, getWorkspaceConnectionConfig, getWorkspacePath, McpOptions, panels, saveWorkspaceConnectionConfig } from "../global";
import * as vscode from 'vscode';
import { t } from "../i18n";
export async function deleteUserConnection(item: McpOptions[] | McpOptions) {
// 弹出确认对话框
const masterNode = Array.isArray(item) ? item[0] : item;
const name = masterNode.name;
const name = masterNode.name || 'unknown node name';
console.log('enter delete');
const confirm = await vscode.window.showWarningMessage(
`确定要删除连接 "${name}" 吗?`,
const res = await vscode.window.showWarningMessage(
t("ensure-delete-connection", name),
{ modal: true },
'确定'
{ title: t('confirm'), value: true },
);
if (confirm !== '确定') {
const confirm = res?.value;
if (!confirm) {
return; // 用户取消删除
}
const workspaceConnectionConfig = getWorkspaceConnectionConfig();
// 从配置中移除该连接项
console.log(item);
console.log(workspaceConnectionConfig.items);
// TODO: 改成基于 path 进行搜索
const index = workspaceConnectionConfig.items.indexOf(item);
@ -53,14 +53,14 @@ export async function validateAndGetCommandPath(command: string, cwd?: string):
const { stdout } = await execAsync(`which ${command.split(' ')[0]}`, { cwd });
return stdout.trim();
} catch (error) {
throw new Error(`无法找到命令: ${command.split(' ')[0]}`);
throw new Error(`Cannot find command: ${command.split(' ')[0]}`);
}
}
export async function acquireUserCustomConnection(): Promise<McpOptions[]> {
// 让用户选择连接类型
const connectionType = await vscode.window.showQuickPick(['STDIO', 'SSE', 'STREAMABLE_HTTP'], {
placeHolder: '请选择连接类型',
placeHolder: t('choose-connection-type'),
canPickMany: false,
ignoreFocusOut: true,
});
@ -72,8 +72,8 @@ export async function acquireUserCustomConnection(): Promise<McpOptions[]> {
if (connectionType === 'STDIO') {
// 获取 command
const commandString = await vscode.window.showInputBox({
prompt: '请输入连接的 command',
placeHolder: '例如: mcp run main.py'
prompt: t('please-enter-connection-command'),
placeHolder: t('example-mcp-run')
});
if (!commandString) {
@ -82,8 +82,8 @@ export async function acquireUserCustomConnection(): Promise<McpOptions[]> {
// 获取 cwd
const cwd = await vscode.window.showInputBox({
prompt: '请输入工作目录 (cwd),可选',
placeHolder: '例如: /path/to/project'
prompt: t('please-enter-cwd'),
placeHolder: t('please-enter-cwd-placeholder')
});
// 校验 command + cwd 是否有效
@ -91,7 +91,7 @@ export async function acquireUserCustomConnection(): Promise<McpOptions[]> {
const commandPath = await validateAndGetCommandPath(commandString, cwd);
console.log('Command Path:', commandPath);
} catch (error) {
vscode.window.showErrorMessage(`无效的 command: ${error}`);
vscode.window.showErrorMessage(`Invalid command: ${error}`);
return [];
}
@ -113,8 +113,8 @@ export async function acquireUserCustomConnection(): Promise<McpOptions[]> {
} else if (connectionType === 'SSE') {
// 获取 url
const url = await vscode.window.showInputBox({
prompt: '请输入连接的 URL',
placeHolder: '例如: https://127.0.0.1:8282/sse'
prompt: t('please-enter-url'),
placeHolder: t('example-as') + 'https://127.0.0.1:8282/sse'
});
if (!url) {
@ -123,8 +123,8 @@ export async function acquireUserCustomConnection(): Promise<McpOptions[]> {
// 获取 oauth
const oauth = await vscode.window.showInputBox({
prompt: '请输入 OAuth 令牌,可选',
placeHolder: '例如: your-oauth-token'
prompt: t('enter-optional-oauth'),
placeHolder: t('example-as') + ' your-oauth-token'
});
// 保存连接配置
@ -138,8 +138,8 @@ export async function acquireUserCustomConnection(): Promise<McpOptions[]> {
} else if (connectionType === 'STREAMABLE_HTTP') {
// 获取 url
const url = await vscode.window.showInputBox({
prompt: '请输入连接的 URL',
placeHolder: '例如: https://127.0.0.1:8282/stream'
prompt: t('please-enter-url'),
placeHolder: t('example-as') + ' https://127.0.0.1:8282/stream'
});
if (!url) {
@ -148,8 +148,8 @@ export async function acquireUserCustomConnection(): Promise<McpOptions[]> {
// 获取 oauth
const oauth = await vscode.window.showInputBox({
prompt: '请输入 OAuth 令牌,可选',
placeHolder: '例如: your-oauth-token'
prompt: t('enter-optional-oauth'),
placeHolder: t('example-as') + ' your-oauth-token'
});
// 保存连接配置

View File

@ -15,8 +15,7 @@ export class WebviewController {
const signature = getDefaultLanunchSignature(uri.fsPath, cwd);
if (!signature) {
vscode.window.showInformationMessage('OpenMCP: 无法获取启动参数');
vscode.window.showErrorMessage('OpenMCP: 无法获取启动参数');
vscode.window.showErrorMessage('OpenMCP: Cannot acquire launch parameters');
return;
}