-
Notifications
You must be signed in to change notification settings - Fork 625
fix: mcp params support more types #861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4b383c8
6d2f01d
a2c4b54
4bf6d56
a104fce
73c5f71
e9d436a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log('contextMenu: final url:', url) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!url) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error('无法获取图片URL,请检查图片源') | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| let fileName = 'image.png' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| let imageBuffer: Buffer | null = null | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 - 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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 重新抛出原始错误 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw fetchError | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| imageBuffer = Buffer.from(await response.arrayBuffer()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!imageBuffer) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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 { | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const results = await Promise.all( | ||||||||||||||||||||||||||||||||||||||||||||
| NPM_REGISTRY_LIST.map(async (registry) => { | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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 { | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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 | ||||||||||||||||||||||||||
| })) | ||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
@@ -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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Array enum values block never renders (wrong condition). You set - 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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| 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> | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainAdditions 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
doneLength of output: 3842 Ensure consistent “invalid JSON” key usage 🤖 Prompt for AI Agents |
||
| }, | ||
| "addServer": "Add Server", | ||
| "addServerDialog": { | ||
|
|
||
There was a problem hiding this comment.
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
pageURLcan try to “save” HTML as an image. Limit fallback tolinkURLonly when it likely points to an image. Also switch the thrown message to English.Also applies to: 96-98
🤖 Prompt for AI Agents