This commit is contained in:
锦恢 2025-06-01 03:40:16 +08:00
parent ab81e276d3
commit 97f89b0833
19 changed files with 253 additions and 64 deletions

View File

@ -1,5 +1,13 @@
# Change Log
## [main] 0.1.2
- 新特性:用户发送的信息增加「重新发送」按钮。
- 支持特性 issue#17 「关于左侧添加mcp服务器操作优化问题」增加强制聚焦功能用户创建mcp服务器连接的过程中不会让输入框失去焦点。
- 更新 MCP & OpenAI 协议内容。
- 解决 issue#21 vscode插件界面bug在高度有限情况下无法通过滚动完全显示连接按钮。
- 解决 issue#21 最后一个标签页关闭并恢复默认页面。
- 解决 issue#22 工具模块UI异常现在 openmcp 支持解析 pydantic 进行 typing 的 python mcp 了。
## [main] 0.1.1
- 修复 SSH 连接 Ubuntu 的情况下的部分 bug
- 修复 python 项目点击 openmcp 进行连接时,初始化参数错误的问题

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 62 KiB

169
package-lock.json generated
View File

@ -1,23 +1,23 @@
{
"name": "openmcp",
"version": "0.1.0",
"version": "0.1.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openmcp",
"version": "0.1.0",
"version": "0.1.1",
"workspaces": [
"service",
"renderer",
"software"
],
"dependencies": {
"@modelcontextprotocol/sdk": "^1.10.2",
"@modelcontextprotocol/sdk": "^1.12.1",
"@seald-io/nedb": "^4.1.1",
"axios": "^1.7.7",
"bson": "^6.8.0",
"openai": "^4.93.0",
"openai": "^5.0.1",
"pako": "^2.1.0",
"tesseract.js": "^6.0.1",
"uuid": "^11.1.0",
@ -1516,12 +1516,12 @@
}
},
"node_modules/@modelcontextprotocol/sdk": {
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.4.tgz",
"integrity": "sha512-OTbhe5slIjiOtLxXhKalkKGhIQrwvhgCDs/C2r8kcBTy5HR/g43aDQU0l7r8O0VGbJPTNJvDc7ZdQMdQDJXmbw==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.12.1.tgz",
"integrity": "sha512-KG1CZhZfWg+u8pxeM/mByJDScJSrjjxLc8fwQqbsS8xCjBmQfMNEBTotYdNanKekepnfRI85GtgQlctLFpcYPw==",
"license": "MIT",
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^6.12.6",
"content-type": "^1.0.5",
"cors": "^2.8.5",
"cross-spawn": "^7.0.5",
@ -1537,6 +1537,28 @@
"node": ">=18"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"license": "MIT"
},
"node_modules/@openmcp/electron": {
"resolved": "software",
"link": true
@ -3238,6 +3260,7 @@
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"dev": true,
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
@ -5852,7 +5875,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true,
"license": "MIT"
},
"node_modules/fast-redact": {
@ -5874,6 +5896,7 @@
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
"integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
"dev": true,
"funding": [
{
"type": "github",
@ -7360,6 +7383,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true,
"license": "MIT"
},
"node_modules/json-stringify-safe": {
@ -8389,19 +8413,10 @@
}
},
"node_modules/openai": {
"version": "4.100.0",
"resolved": "https://registry.npmjs.org/openai/-/openai-4.100.0.tgz",
"integrity": "sha512-9soq/wukv3utxcuD7TWFqKdKp0INWdeyhUCvxwrne5KwnxaCp4eHL4GdT/tMFhYolxgNhxFzg5GFwM331Z5CZg==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/openai/-/openai-5.0.1.tgz",
"integrity": "sha512-Do6vxhbDv7cXhji/4ct1lrpZYMAOmjYbhyA9LJTuG7OfpbWMpuS+EIXkRT7R+XxpRB1OZhU/op4FU3p3uxU6gw==",
"license": "Apache-2.0",
"dependencies": {
"@types/node": "^18.11.18",
"@types/node-fetch": "^2.6.4",
"abort-controller": "^3.0.0",
"agentkeepalive": "^4.2.1",
"form-data-encoder": "1.7.2",
"formdata-node": "^4.3.2",
"node-fetch": "^2.6.7"
},
"bin": {
"openai": "bin/cli"
},
@ -8418,21 +8433,6 @@
}
}
},
"node_modules/openai/node_modules/@types/node": {
"version": "18.19.101",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.101.tgz",
"integrity": "sha512-Ykg7fcE3+cOQlLUv2Ds3zil6DVjriGQaSN/kEpl5HQ3DIGM6W0F2n9+GkWV4bRt7KjLymgzNdTnSKCbFUUJ7Kw==",
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/openai/node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"license": "MIT"
},
"node_modules/opencollective-postinstall": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
@ -8965,7 +8965,6 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@ -9198,6 +9197,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@ -10725,7 +10725,6 @@
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"punycode": "^2.1.0"
@ -11448,6 +11447,51 @@
"node": ">=14.14"
}
},
"renderer/node_modules/openai": {
"version": "4.104.0",
"resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz",
"integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==",
"license": "Apache-2.0",
"dependencies": {
"@types/node": "^18.11.18",
"@types/node-fetch": "^2.6.4",
"abort-controller": "^3.0.0",
"agentkeepalive": "^4.2.1",
"form-data-encoder": "1.7.2",
"formdata-node": "^4.3.2",
"node-fetch": "^2.6.7"
},
"bin": {
"openai": "bin/cli"
},
"peerDependencies": {
"ws": "^8.18.0",
"zod": "^3.23.8"
},
"peerDependenciesMeta": {
"ws": {
"optional": true
},
"zod": {
"optional": true
}
}
},
"renderer/node_modules/openai/node_modules/@types/node": {
"version": "18.19.110",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.110.tgz",
"integrity": "sha512-WW2o4gTmREtSnqKty9nhqF/vA0GKd0V/rbC0OyjSk9Bz6bzlsXKT+i7WDdS/a0z74rfT2PO4dArVCSnapNLA5Q==",
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"renderer/node_modules/openai/node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"license": "MIT"
},
"renderer/node_modules/vite": {
"version": "6.3.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
@ -11603,9 +11647,9 @@
"version": "0.0.1",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.10.2",
"@modelcontextprotocol/sdk": "^1.12.1",
"@seald-io/nedb": "^4.1.1",
"openai": "^4.96.0",
"openai": "^5.0.1",
"pako": "^2.1.0",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0",
@ -11785,6 +11829,51 @@
"electron-builder": "^24.13.3",
"typescript": "^5.6.3"
}
},
"software/node_modules/@types/node": {
"version": "18.19.110",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.110.tgz",
"integrity": "sha512-WW2o4gTmREtSnqKty9nhqF/vA0GKd0V/rbC0OyjSk9Bz6bzlsXKT+i7WDdS/a0z74rfT2PO4dArVCSnapNLA5Q==",
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"software/node_modules/openai": {
"version": "4.104.0",
"resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz",
"integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==",
"license": "Apache-2.0",
"dependencies": {
"@types/node": "^18.11.18",
"@types/node-fetch": "^2.6.4",
"abort-controller": "^3.0.0",
"agentkeepalive": "^4.2.1",
"form-data-encoder": "1.7.2",
"formdata-node": "^4.3.2",
"node-fetch": "^2.6.7"
},
"bin": {
"openai": "bin/cli"
},
"peerDependencies": {
"ws": "^8.18.0",
"zod": "^3.23.8"
},
"peerDependenciesMeta": {
"ws": {
"optional": true
},
"zod": {
"optional": true
}
}
},
"software/node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"license": "MIT"
}
}
}

View File

@ -2,7 +2,7 @@
"name": "openmcp",
"displayName": "OpenMCP",
"description": "An all in one MCP Client/TestTool",
"version": "0.1.1",
"version": "0.1.2",
"publisher": "kirigaya",
"author": {
"name": "kirigaya",
@ -233,11 +233,11 @@
"build:task-loop": "webpack --config webpack/webpack.task-loop.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.10.2",
"@modelcontextprotocol/sdk": "^1.12.1",
"@seald-io/nedb": "^4.1.1",
"axios": "^1.7.7",
"bson": "^6.8.0",
"openai": "^4.93.0",
"openai": "^5.0.1",
"pako": "^2.1.0",
"tesseract.js": "^6.0.1",
"uuid": "^11.1.0",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -16,6 +16,9 @@
<el-button @click="copy">
<span class="iconfont icon-copy"></span>
</el-button>
<el-button @click="reload">
<span class="iconfont icon-restart"></span>
</el-button>
<el-button @click="toggleEdit">
<span class="iconfont icon-edit2"></span>
</el-button>
@ -91,6 +94,16 @@ const copy = async () => {
}
};
const reload = async () => {
const index = tabStorage.messages.findIndex(msg => msg.extraInfo === props.message.extraInfo);
if (index !== -1 && chatContext.handleSend) {
// index index
tabStorage.messages.splice(index);
chatContext.handleSend(props.message.content);
}
};
</script>
<style>

View File

@ -60,7 +60,7 @@ export function createTab(type: string, index: number): Tab {
if (customName !== null) {
return customName;
}
return t('blank-test') + ` ${index}`;
return t('blank-test');
},
set name(value: string) {
customName = value; // 允许外部修改 name
@ -85,8 +85,6 @@ export function addNewTab() {
export function closeTab(index: number) {
if (tabs.content.length <= 1) return; // 至少保留一个标签页
tabs.content.splice(index, 1);
console.log(tabs.content);
@ -95,4 +93,8 @@ export function closeTab(index: number) {
if (tabs.activeIndex >= index) {
tabs.activeIndex = Math.max(0, tabs.activeIndex - 1);
}
if (tabs.content.length === 0) {
addNewTab();
}
}

View File

@ -90,16 +90,23 @@ console.log(tabStorage.formData);
const formRef = ref<FormInstance>();
const loading = ref(false);
const currentTool = computed(() => {
for (const client of mcpClientAdapter.clients) {
const tool = client.tools?.get(tabStorage.currentToolName);
if (tool) return tool;
if (tool) {
console.log(tool);
return tool;
}
}
});
const formRules = computed<FormRules>(() => {
const rules: FormRules = {};
if (!currentTool.value?.inputSchema?.properties) return rules;
Object.entries(currentTool.value.inputSchema.properties).forEach(([name, property]) => {

View File

@ -10,6 +10,7 @@ export interface InputSchema {
properties: Record<string, SchemaProperty>;
required?: string[];
title?: string;
$defs?: any;
}
export interface Argument {
@ -40,6 +41,7 @@ export interface ToolItem {
name: string;
description: string;
inputSchema: InputSchema;
anyOf?: any;
}
export interface ToolsListResponse {
tools: ToolItem[]

View File

@ -6,7 +6,7 @@
</span>
<p>
OpenMCP Client 0.1.1 OpenMCP@<a href="https://www.zhihu.com/people/can-meng-zhong-de-che-xian">锦恢</a> 开发
OpenMCP Client 0.1.2 OpenMCP@<a href="https://www.zhihu.com/people/can-meng-zhong-de-che-xian">锦恢</a> 开发
</p>
<p>

View File

@ -121,4 +121,9 @@ const validateForm = async () => {
border-radius: 4px;
margin-bottom: 16px;
}
.connection-option .el-form-item {
margin-bottom: 0;
}
</style>

View File

@ -53,7 +53,7 @@ function clearLogs() {
<style>
.connection-log {
height: 90vh;
height: 100%;
display: flex;
flex-direction: column;
gap: 12px;

View File

@ -1,5 +1,5 @@
<template>
<el-scrollbar>
<el-scrollbar height="98%">
<div class="connection-container" @dragover.prevent="handleDragOver" @drop.prevent="handleDrop">
<div v-if="isDraging" class="drag-mask">
<span class="iconfont icon-connect"></span>
@ -24,7 +24,6 @@
</div>
</div>
</el-scrollbar>
</template>
<script setup lang="ts">
@ -126,6 +125,7 @@ function handleDrop(event: DragEvent) {
<style>
.connection-container {
display: flex;
max-height: 85vh;
}
@ -133,7 +133,6 @@ function handleDrop(event: DragEvent) {
display: flex;
flex-direction: column;
width: 45%;
max-height: 85vh;
max-width: 500px;
min-width: 350px;
padding: 5px 20px;
@ -143,7 +142,6 @@ function handleDrop(event: DragEvent) {
display: flex;
flex-direction: column;
width: 55%;
max-height: 85vh;
min-width: 450px;
padding: 5px 20px;
}

View File

@ -30,6 +30,66 @@ function prettifyMapKeys(keys: MapIterator<string>) {
return result.join('\n');
}
function _processSchemaNode(node: any, defs: Record<string, any> = {}): any {
// Handle $ref references
if ('$ref' in node) {
const refPath = node['$ref'];
if (refPath.startsWith('#/$defs/')) {
const refName = refPath.split('/').pop();
if (refName && refName in defs) {
// Process the referenced definition
return _processSchemaNode(defs[refName], defs);
}
}
}
// Start with a new schema object
const result: Record<string, any> = {};
// Copy the basic properties
if ('type' in node) {
result.type = node.type;
}
// Handle anyOf (often used for optional fields with None)
if ('anyOf' in node) {
const nonNullTypes = node.anyOf.filter((t: any) => t?.type !== 'null');
if (nonNullTypes.length > 0) {
// Process the first non-null type
const processed = _processSchemaNode(nonNullTypes[0], defs);
Object.assign(result, processed);
}
}
// Handle description
if ('description' in node) {
result.description = node.description;
}
// Handle object properties recursively
if (node?.type === 'object' && 'properties' in node) {
result.type = 'object';
result.properties = {};
// Process each property
for (const [propName, propSchema] of Object.entries(node.properties)) {
result.properties[propName] = _processSchemaNode(propSchema as any, defs);
}
// Add required fields if present
if ('required' in node) {
result.required = node.required;
}
}
// Handle arrays
if (node?.type === 'array' && 'items' in node) {
result.type = 'array';
result.items = _processSchemaNode(node.items, defs);
}
return result;
}
export class McpClient {
// 连接入参
@ -139,6 +199,11 @@ export class McpClient {
this.tools = new Map<string, ToolItem>();
msg.tools.forEach(tool => {
const standardSchema = _processSchemaNode(tool.inputSchema, tool.inputSchema.$defs || {});
console.log(standardSchema);
tool.inputSchema = standardSchema;
this.tools!.set(tool.name, tool);
});

View File

@ -104,18 +104,15 @@ function deleteServer(index: number) {
display: flex;
align-items: center;
width: 150px;
height: 50px;
border-right: 1px solid var(--border-color);
padding: 15px 25px;
padding: 0 25px;
}
.server-name {
font-size: 15px;
font-size: 12px;
}
.server-item {
padding: 10px;
margin-bottom: 5px;
cursor: pointer;
border-radius: 4px;
display: flex;

View File

@ -36,9 +36,9 @@
"webpack-node-externals": "^3.0.0"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.10.2",
"@modelcontextprotocol/sdk": "^1.12.1",
"@seald-io/nedb": "^4.1.1",
"openai": "^4.96.0",
"openai": "^5.0.1",
"pako": "^2.1.0",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0",

View File

@ -299,4 +299,4 @@ export async function connectService(
return connectResult;
}
}
}

View File

@ -58,7 +58,8 @@ export async function acquireInstalledConnection(): Promise<McpOptions[]> {
// 让用户选择连接类型
const connectionType = await vscode.window.showQuickPick(['STDIO', 'SSE', 'STREAMABLE_HTTP'], {
placeHolder: '请选择连接类型',
canPickMany: false
canPickMany: false,
ignoreFocusOut: true,
});
if (!connectionType) {

View File

@ -59,8 +59,10 @@ export async function validateAndGetCommandPath(command: string, cwd?: string):
export async function acquireUserCustomConnection(): Promise<McpOptions[]> {
// 让用户选择连接类型
const connectionType = await vscode.window.showQuickPick(['STDIO', 'SSE'], {
placeHolder: '请选择连接类型'
const connectionType = await vscode.window.showQuickPick(['STDIO', 'SSE', 'STREAMABLE_HTTP'], {
placeHolder: '请选择连接类型',
canPickMany: false,
ignoreFocusOut: true,
});
if (!connectionType) {