Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions src/main/contextMenuHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,26 @@ export default function contextMenu(options: ContextMenuOptions): () => void {
click: async () => {
try {
// 获取文件名和URL
const url = params.srcURL || ''
let url = params.srcURL || ''
console.log('contextMenu: all params available:', Object.keys(params))
console.log('contextMenu: srcURL:', params.srcURL)
console.log('contextMenu: linkURL:', params.linkURL)
console.log('contextMenu: pageURL:', params.pageURL)

// 如果srcURL为空,尝试其他可能的URL来源
if (!url && params.linkURL) {
url = params.linkURL
}
if (!url && params.pageURL) {
url = params.pageURL
}

Comment on lines +86 to +93
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Over-broad URL fallback; avoid using pageURL and improve error text.

Falling back to pageURL can try to “save” HTML as an image. Limit fallback to linkURL only when it likely points to an image. Also switch the thrown message to English.

-            // 如果srcURL为空,尝试其他可能的URL来源
-            if (!url && params.linkURL) {
-              url = params.linkURL
-            }
-            if (!url && params.pageURL) {
-              url = params.pageURL
-            }
+            // If srcURL is empty, consider linkURL only when it looks like an image
+            if (!url && params.linkURL && /\.(png|jpe?g|gif|webp|bmp|svg)(\?.*)?$/i.test(params.linkURL)) {
+              url = params.linkURL
+            }
@@
-            if (!url) {
-              throw new Error('无法获取图片URL,请检查图片源')
-            }
+            if (!url) {
+              throw new Error('Unable to resolve an image URL from the context. Please check the image source.')
+            }

Also applies to: 96-98

🤖 Prompt for AI Agents
In src/main/contextMenuHelper.ts around lines 86-93 (and likewise update lines
96-98), the current fallback to params.pageURL is too broad and the thrown error
text is not English; restrict fallback to params.linkURL only when it likely
points to an image (e.g., check for data:image/*, common image extensions like
.png/.jpg/.jpeg/.gif/.webp or a Content-Type header if available) and remove any
use of params.pageURL as a fallback; also change thrown error messages to clear
English text (e.g., "No valid image URL found") and apply the same logic and
message update at the later block covering lines 96-98.

console.log('contextMenu: final url:', url)

if (!url) {
throw new Error('无法获取图片URL,请检查图片源')
}

let fileName = 'image.png'
let imageBuffer: Buffer | null = null

Expand Down Expand Up @@ -110,6 +129,7 @@ export default function contextMenu(options: ContextMenuOptions): () => void {
}

console.log('contextMenu: start saving pic', filePath)
console.log('contextMenu: source URL:', url)

// 获取图片数据
if (isBase64) {
Expand All @@ -121,11 +141,30 @@ export default function contextMenu(options: ContextMenuOptions): () => void {
imageBuffer = Buffer.from(base64Data, 'base64')
} else {
// 处理普通URL
const response = await net.fetch(url)
if (!response.ok) {
throw new Error(`下载图片失败: ${response.status}`)
try {
const response = await net.fetch(url)
if (!response.ok) {
throw new Error(`下载图片失败: ${response.status}`)
}
imageBuffer = Buffer.from(await response.arrayBuffer())
} catch (fetchError) {
console.error('contextMenu: fetch failed, trying alternative methods:', fetchError)

// 如果net.fetch失败,尝试其他方法
if (url.startsWith('file://')) {
// 处理file:// URL
const fs = require('fs').promises
const filePath = url.substring(7) // 移除 file:// 前缀
imageBuffer = await fs.readFile(filePath)
} else if (url.startsWith('/') || url.match(/^[A-Za-z]:\\/)) {
// 处理本地文件路径(Unix或Windows格式)
const fs = require('fs').promises
imageBuffer = await fs.readFile(url)
} else {
Comment on lines +154 to +163
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Robust file:// and local-path handling (decode URL, support more Windows/UNC forms).

Use fileURLToPath for file:// URIs, avoid shadowing filePath, and cover C:/ and UNC paths.

-                if (url.startsWith('file://')) {
-                  // 处理file:// URL
-                  const fs = require('fs').promises
-                  const filePath = url.substring(7) // 移除 file:// 前缀
-                  imageBuffer = await fs.readFile(filePath)
-                } else if (url.startsWith('/') || url.match(/^[A-Za-z]:\\/)) {
-                  // 处理本地文件路径(Unix或Windows格式)
-                  const fs = require('fs').promises
-                  imageBuffer = await fs.readFile(url)
+                if (url.startsWith('file://')) {
+                  // file:// URL -> decode to local path
+                  const fs = require('fs').promises
+                  const { fileURLToPath } = require('url')
+                  const localPath = fileURLToPath(url)
+                  imageBuffer = await fs.readFile(localPath)
+                } else if (url.startsWith('/') || /^[A-Za-z]:[\\/]/.test(url) || url.startsWith('\\\\')) {
+                  // Absolute Unix path, Windows drive path (C:\ or C:/), or UNC path
+                  const fs = require('fs').promises
+                  imageBuffer = await fs.readFile(url)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (url.startsWith('file://')) {
// 处理file:// URL
const fs = require('fs').promises
const filePath = url.substring(7) // 移除 file:// 前缀
imageBuffer = await fs.readFile(filePath)
} else if (url.startsWith('/') || url.match(/^[A-Za-z]:\\/)) {
// 处理本地文件路径(Unix或Windows格式)
const fs = require('fs').promises
imageBuffer = await fs.readFile(url)
} else {
if (url.startsWith('file://')) {
// file:// URL -> decode to local path
const fs = require('fs').promises
const { fileURLToPath } = require('url')
const localPath = fileURLToPath(url)
imageBuffer = await fs.readFile(localPath)
} else if (
url.startsWith('/') ||
/^[A-Za-z]:[\\/]/.test(url) ||
url.startsWith('\\\\')
) {
// Absolute Unix path, Windows drive path (C:\ or C:/), or UNC path
const fs = require('fs').promises
imageBuffer = await fs.readFile(url)
} else {
🤖 Prompt for AI Agents
In src/main/contextMenuHelper.ts around lines 154 to 163, the file:// and
local-path handling is fragile: use fileURLToPath to decode file:// URIs, avoid
reusing the variable name filePath, and expand Windows path matching to accept
drive paths with forward slashes (e.g. C:/path) and UNC paths
(\\\\server\\share). Import or require fileURLToPath from 'url' and use it to
convert the file:// URL into a safe filesystem path, then call
fs.promises.readFile on that path; for local paths, broaden the regex to match
^[A-Za-z]:[\\/]|^\\\\\\\\ to detect drives and UNC, and normalize the path with
path.normalize before reading. Ensure variable names are unique (e.g., urlPath)
and handle errors from readFile appropriately.

// 重新抛出原始错误
throw fetchError
}
}
imageBuffer = Buffer.from(await response.arrayBuffer())
}

if (!imageBuffer) {
Expand Down
32 changes: 19 additions & 13 deletions src/main/presenter/mcpPresenter/serverManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { MCP_EVENTS } from '@/events'
import { getErrorMessageLabels } from '@shared/i18n'

const NPM_REGISTRY_LIST = [
'https://registry.npmmirror.com/',
'https://registry.npmjs.org/',
'https://r.cnpmjs.org/',
'https://registry.npmmirror.com/'
'https://r.cnpmjs.org/'
]

export class ServerManager {
Expand Down Expand Up @@ -68,14 +68,19 @@ export class ServerManager {
}

console.log('[NPM Registry] Testing registry speed...')
const timeout = 3000
const timeout = 10000
const testPackage = 'tiny-runtime-injector'

// 获取代理配置
const proxyUrl = proxyConfig.getProxyUrl()
const proxyOptions = proxyUrl
? { proxy: { host: new URL(proxyUrl).hostname, port: parseInt(new URL(proxyUrl).port) } }
: {}
const proxyOptions = (() => {
if (!proxyUrl) return {}
const u = new URL(proxyUrl)
const host = u.hostname
const port = u.port ? parseInt(u.port, 10) : u.protocol === 'https:' ? 443 : 80
const auth = u.username ? { username: u.username, password: u.password ?? '' } : undefined
return { proxy: { host, port, ...(auth ? { auth } : {}) } }
})()
Comment on lines +76 to +83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Proxy parsing: restrict schemes and handle HTTPS proxies correctly

Axios’s built-in proxy option supports HTTP proxies; HTTPS/SOCKS usually require agent-based proxying. Guard unknown schemes and avoid misconfig. Example minimal guard:

-    const proxyOptions = (() => {
-      if (!proxyUrl) return {}
-      const u = new URL(proxyUrl)
-      const host = u.hostname
-      const port = u.port ? parseInt(u.port, 10) : u.protocol === 'https:' ? 443 : 80
-      const auth = u.username ? { username: u.username, password: u.password ?? '' } : undefined
-      return { proxy: { host, port, ...(auth ? { auth } : {}) } }
-    })()
+    const proxyOptions = (() => {
+      if (!proxyUrl) return {}
+      const u = new URL(proxyUrl)
+      if (u.protocol !== 'http:' && u.protocol !== 'https:') {
+        console.warn(`[NPM Registry] Unsupported proxy scheme: ${u.protocol}; ignoring for speed test`)
+        return {}
+      }
+      const scheme = u.protocol === 'https:' ? 'https' : 'http'
+      const host = u.hostname
+      const port = u.port ? parseInt(u.port, 10) : scheme === 'https' ? 443 : 80
+      const auth = u.username ? { username: u.username, password: u.password ?? '' } : undefined
+      return { proxy: { host, port, ...(auth ? { auth } : {}) } }
+    })()

If HTTPS proxy support is needed, switch to http(s)-proxy-agent via httpAgent/httpsAgent with proxy: false. I can provide a patch if desired.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const proxyOptions = (() => {
if (!proxyUrl) return {}
const u = new URL(proxyUrl)
const host = u.hostname
const port = u.port ? parseInt(u.port, 10) : u.protocol === 'https:' ? 443 : 80
const auth = u.username ? { username: u.username, password: u.password ?? '' } : undefined
return { proxy: { host, port, ...(auth ? { auth } : {}) } }
})()
const proxyOptions = (() => {
if (!proxyUrl) return {}
const u = new URL(proxyUrl)
if (u.protocol !== 'http:' && u.protocol !== 'https:') {
console.warn(`[NPM Registry] Unsupported proxy scheme: ${u.protocol}; ignoring for speed test`)
return {}
}
const scheme = u.protocol === 'https:' ? 'https' : 'http'
const host = u.hostname
const port = u.port ? parseInt(u.port, 10) : scheme === 'https' ? 443 : 80
const auth = u.username ? { username: u.username, password: u.password ?? '' } : undefined
return { proxy: { host, port, ...(auth ? { auth } : {}) } }
})()
🤖 Prompt for AI Agents
In src/main/presenter/mcpPresenter/serverManager.ts around lines 76 to 83, the
current proxyUrl parsing unconditionally accepts any URL scheme and treats
'https:' like an HTTP proxy (setting port 443), which misconfigures Axios (it
only supports HTTP proxies via its proxy option); update the code to only accept
http: proxies for the Axios proxy option (e.g., if u.protocol !== 'http:' then
return {} or fail fast/log a clear error), keep the host/port/auth extraction
for http:, and if HTTPS or other proxy schemes are required switch to using an
agent (http(s)-proxy-agent) and set axios proxy: false while wiring the agent
into httpAgent/httpsAgent; ensure you handle missing port, parseInt safely, and
avoid passing unsupported schemes into Axios proxy.


const results = await Promise.all(
NPM_REGISTRY_LIST.map(async (registry) => {
Expand All @@ -84,21 +89,22 @@ export class ServerManager {
let isTimeout = false
let time = 0

const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), timeout)
try {
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), timeout)

const response = await axios.get(`${registry}${testPackage}`, {
...proxyOptions,
signal: controller.signal
})

clearTimeout(timeoutId)
success = response.status >= 200 && response.status < 300
time = Date.now() - start
} catch (error) {
isTimeout =
(error instanceof Error &&
(error.name === 'AbortError' || error.name === 'CanceledError')) ||
Date.now() - start >= timeout
} finally {
clearTimeout(timeoutId)
time = Date.now() - start
isTimeout = (error instanceof Error && error.name === 'AbortError') || time >= timeout
}

return {
Expand Down
74 changes: 69 additions & 5 deletions src/renderer/src/components/mcp-config/components/McpToolPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,16 @@ const toolParametersDescription = computed(() => {
return Object.entries(properties).map(([key, prop]) => ({
name: key,
description: prop.description || '',
type: prop.type || 'unknown',
type: prop.enum
? 'enum'
: prop.type === 'array' && prop.items?.enum
? 'array[enum]'
: prop.type || 'unknown',
originalType: prop.type || 'unknown',
required: required.includes(key),
annotations: prop.annotations
annotations: prop.annotations,
enum: prop.enum || null,
items: prop.items || null
}))
})

Expand Down Expand Up @@ -289,13 +296,70 @@ const selectTool = (tool: MCPToolDefinition) => {
>
{{ t('mcp.tools.required') }}
</Badge>
<Badge variant="outline" class="text-xs px-1 py-0">{{
param.type
}}</Badge>
<Badge
:variant="
param.type === 'enum' || param.type === 'array[enum]'
? 'default'
: 'outline'
"
class="text-xs px-1 py-0"
:class="
param.type === 'enum' || param.type === 'array[enum]'
? 'bg-blue-500 text-white'
: ''
"
>
{{
param.type === 'enum'
? `enum(${param.originalType})`
: param.type === 'array[enum]'
? `array[enum(${param.items?.type || 'string'})]`
: param.type
}}
</Badge>
</div>
<p v-if="param.description" class="text-xs text-muted-foreground">
{{ param.description }}
</p>
<!-- 显示枚举值 -->
<div v-if="param.enum && param.enum.length > 0" class="mt-1">
<p class="text-xs font-medium text-foreground mb-1">
{{ t('mcp.tools.allowedValues') }}:
</p>
<div class="flex flex-wrap gap-1">
<Badge
v-for="enumValue in param.enum"
:key="enumValue"
variant="secondary"
class="text-xs px-1.5 py-0.5 font-mono"
>
{{ enumValue }}
</Badge>
</div>
</div>
<!-- 显示数组元素类型的枚举值 -->
<div
v-if="
param.type === 'array' &&
param.items?.enum &&
param.items.enum.length > 0
"
Comment on lines +341 to +346
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Array enum values block never renders (wrong condition).

You set param.type to 'array[enum]' earlier, but this block checks param.type === 'array', so it never shows. Switch to param.originalType (kept as the raw JSON Schema type) and harden the guards.

-                          v-if="
-                            param.type === 'array' &&
-                            param.items?.enum &&
-                            param.items.enum.length > 0
-                          "
+                          v-if="
+                            (param.originalType === 'array' || param.type === 'array[enum]') &&
+                            Array.isArray(param.items?.enum) &&
+                            param.items.enum.length > 0
+                          "
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
v-if="
param.type === 'array' &&
param.items?.enum &&
param.items.enum.length > 0
"
<div
v-if="
(param.originalType === 'array' || param.type === 'array[enum]') &&
Array.isArray(param.items?.enum) &&
param.items.enum.length > 0
"
🤖 Prompt for AI Agents
In src/renderer/src/components/mcp-config/components/McpToolPanel.vue around
lines 341-346, the block that should render array enum values uses the wrong
type check (param.type === 'array') so it never runs because param.type was set
to 'array[enum]'; change the condition to check the raw JSON Schema type
(param.originalType === 'array') and harden the guards by verifying param.items
is a non-null object and that Array.isArray(param.items.enum) &&
param.items.enum.length > 0 before rendering. Ensure you use strict checks
(param.originalType === 'array', param.items && typeof param.items === 'object',
Array.isArray(param.items.enum)) to avoid runtime errors.

class="mt-1"
>
<p class="text-xs font-medium text-foreground mb-1">
{{ t('mcp.tools.arrayItemValues') }}:
</p>
<div class="flex flex-wrap gap-1">
<Badge
v-for="enumValue in param.items.enum"
:key="enumValue"
variant="secondary"
class="text-xs px-1.5 py-0.5 font-mono"
>
{{ enumValue }}
</Badge>
</div>
</div>
</div>
</div>
</div>
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/i18n/en-US/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
"jsonInputPlaceholder": "Enter the parameters in JSON format",
"type": "Type",
"annotations": "Annotations",
"invalidJsonFormat": "JSON format is incorrect"
"invalidJsonFormat": "JSON format is incorrect",
"allowedValues": "Allowed values",
"arrayItemValues": "Array item values"
Comment on lines +42 to +44
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Additions look good; verify duplicate “invalid JSON” keys usage.

Both tools.invalidJson and tools.invalidJsonFormat now exist; confirm components reference the intended one to avoid drift.

Run to check key usage and locale coverage:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
# 1) Ensure components reference the new keys
rg -nP --type=vue --type=ts -C2 "t\\(['\"`]mcp\\.tools\\.(allowedValues|arrayItemValues)['\"`]\\)"

# 2) Ensure all locales define both keys
fd mcp.json src/renderer/src/i18n -x jq -e '.[].tools.allowedValues, .[].tools.arrayItemValues' >/dev/null && echo "All locales OK" || echo "Missing keys in some locale"

Length of output: 383


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "1) Checking component references for allowedValues and arrayItemValues..."
rg -n -C2 --glob '*.vue' --glob '*.ts' "t\s*\(\s*['\"]mcp\.tools\.(allowedValues|arrayItemValues)['\"]\s*\)"

echo "2) Checking component references for invalidJson and invalidJsonFormat..."
rg -n -C2 --glob '*.vue' --glob '*.ts' "t\s*\(\s*['\"]mcp\.tools\.(invalidJson|invalidJsonFormat)['\"]\s*\)"

echo "3) Ensuring every locale defines both allowedValues and arrayItemValues..."
for f in src/renderer/src/i18n/*/mcp.json; do
  if ! jq -e '.tools.allowedValues and .tools.arrayItemValues' "$f" >/dev/null; then
    echo "Missing key in $f"
  fi
done

Length of output: 3842


Ensure consistent “invalid JSON” key usage
The component still calls t('mcp.tools.invalidJson') (McpToolPanel.vue:401) but the new invalidJsonFormat key is never used—either update the component to use invalidJsonFormat or remove that unused key from all locales.

🤖 Prompt for AI Agents
In src/renderer/src/i18n/en-US/mcp.json around lines 42 to 44, the locale
defines "invalidJsonFormat" but the component still calls
t('mcp.tools.invalidJson'); align keys by either updating the component to use
t('mcp.tools.invalidJsonFormat') everywhere it references this message
(McpToolPanel.vue and any other usages), or rename the locale key to
"invalidJson" (and propagate that rename to all locale files) so all locales and
components use the same key; ensure you update every locale file consistently
and run a quick search to verify no stale key references remain.

},
"addServer": "Add Server",
"addServerDialog": {
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/i18n/fa-IR/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
"jsonInputPlaceholder": "داده‌ها را در قالب JSON وارد کنید",
"type": "نوع",
"annotations": "حاشیه‌نویسی",
"invalidJsonFormat": "قالب JSON نادرست است"
"invalidJsonFormat": "قالب JSON نادرست است",
"allowedValues": "مقادیر مجاز",
"arrayItemValues": "مقادیر عنصر آرایه"
},
"addServer": "افزودن کارساز",
"addServerDialog": {
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/i18n/fr-FR/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
"invalidJson": "Format JSON invalide",
"inputHint": "Veuillez entrer les paramètres au format JSON",
"required": "Requis",
"noDescription": "Pas de description"
"noDescription": "Pas de description",
"allowedValues": "Valeurs autorisées",
"arrayItemValues": "Valeurs des éléments du tableau"
},
"addServer": "Ajouter un serveur",
"addServerDialog": {
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/src/i18n/ja-JP/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
"enabledDescription": "ツール呼び出しを使用するためにMCP機能を有効にします",
"empty": "空",
"invalidJsonFormat": "無効なJSON形式",
"allowedValues": "許容値",
"arrayItemValues": "配列要素の値",
"jsonInputPlaceholder": "JSON形式でパラメータを入力",
"input": "パラメータ入力",
"type": "タイプ",
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/i18n/ko-KR/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@
"invalidJson": "잘못된 JSON 형식",
"inputHint": "JSON 형식으로 매개변수를 입력하세요",
"required": "필수",
"noDescription": "설명 없음"
"noDescription": "설명 없음",
"allowedValues": "허용되는 값",
"arrayItemValues": "배열 요소 값"
},
"inmemory": {
"Artifacts": {
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/i18n/ru-RU/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
"invalidJson": "Неверный формат JSON",
"inputHint": "Пожалуйста, введите параметры в формате JSON",
"required": "Обязательно",
"noDescription": "Нет описания"
"noDescription": "Нет описания",
"allowedValues": "Разрешенные значения",
"arrayItemValues": "Значения элемента массива"
},
"addServer": "Добавить сервер",
"addServerDialog": {
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/i18n/zh-CN/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@
"type": "类型",
"annotations": "注解",
"empty": "空",
"invalidJsonFormat": "JSON格式不正确"
"invalidJsonFormat": "JSON格式不正确",
"allowedValues": "允许的值",
"arrayItemValues": "数组元素值"
},
"inmemory": {
"bochaSearch": {
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/i18n/zh-HK/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
"invalidJson": "無效的 JSON 格式",
"inputHint": "請以 JSON 格式輸入參數",
"required": "必填",
"noDescription": "無描述"
"noDescription": "無描述",
"allowedValues": "允許的值",
"arrayItemValues": "陣列項目值"
},
"addServer": "添加服務器",
"addServerDialog": {
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/i18n/zh-TW/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@
"invalidJson": "無效的 JSON 格式",
"inputHint": "請以 JSON 格式輸入參數",
"required": "必填",
"noDescription": "無描述"
"noDescription": "無描述",
"allowedValues": "允許的值",
"arrayItemValues": "陣列元素值"
},
"inmemory": {
"Artifacts": {
Expand Down