From 3976670295af95488ea93b51acfe46b7dd02ab3f Mon Sep 17 00:00:00 2001
From: Kirigaya <1193466151@qq.com>
Date: Tue, 22 Apr 2025 15:13:54 +0800
Subject: [PATCH] push save MVP to 95%
---
.gitignore | 4 ++-
.vscode-test.mjs | 5 ---
CHANGELOG.md | 3 ++
package.json | 2 +-
.../main-panel/resource/resouce-reader.vue | 33 +++++++++++++------
.../resource/resource-templates.vue | 5 ++-
.../main-panel/resource/resources.ts | 7 ++--
.../main-panel/tool/tool-executor.vue | 18 ++--------
renderer/src/hook/mcp.ts | 30 +++++++++++++++++
service/tabs.锦恢的 MCP Server.json | 25 ++++++++++++--
10 files changed, 92 insertions(+), 40 deletions(-)
delete mode 100644 .vscode-test.mjs
create mode 100644 renderer/src/hook/mcp.ts
diff --git a/.gitignore b/.gitignore
index 02c03a0..40ccff1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,6 @@ node_modules
.vscode-test/
*.vsix
.env
-resources
\ No newline at end of file
+resources
+.DS_Store
+.exe
\ No newline at end of file
diff --git a/.vscode-test.mjs b/.vscode-test.mjs
deleted file mode 100644
index b62ba25..0000000
--- a/.vscode-test.mjs
+++ /dev/null
@@ -1,5 +0,0 @@
-import { defineConfig } from '@vscode/test-cli';
-
-export default defineConfig({
- files: 'out/test/**/*.test.js',
-});
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 667b329..f32ec6f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
# Change Log
+## [main] 0.0.5
+- 支持对已经打开过的文件项目进行管理
+
## [main] 0.0.4
- 修复选择模型后点击确认跳转回 deepseek 的 bug
- 修复 mcp 项目初始化点击工具全部都是空的 bug
diff --git a/package.json b/package.json
index b3fba7e..bf79d2e 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "openmcp",
"displayName": "OpenMCP",
"description": "An all in one MCP Client/TestTool",
- "version": "0.0.4",
+ "version": "0.0.5",
"publisher": "kirigaya",
"author": {
"name": "kirigaya",
diff --git a/renderer/src/components/main-panel/resource/resouce-reader.vue b/renderer/src/components/main-panel/resource/resouce-reader.vue
index e3518d4..973364a 100644
--- a/renderer/src/components/main-panel/resource/resouce-reader.vue
+++ b/renderer/src/components/main-panel/resource/resouce-reader.vue
@@ -3,19 +3,19 @@
{{ currentResource.template?.name }}
-
+
-
-
-
+
@@ -38,6 +38,7 @@ import { tabs } from '../panel';
import { parseResourceTemplate, resourcesManager, ResourceStorage } from './resources';
import { CasualRestAPI, ResourcesReadResponse } from '@/hook/type';
import { useMessageBridge } from '@/api/message-bridge';
+import { getDefaultValue, normaliseJavascriptType } from '@/hook/mcp';
defineComponent({ name: 'resource-reader' });
@@ -53,9 +54,12 @@ const props = defineProps({
const tab = tabs.content[props.tabId];
const tabStorage = tab.storage as ResourceStorage;
+if (!tabStorage.formData) {
+ tabStorage.formData = {};
+}
+
// 表单相关状态
const formRef = ref();
-const formData = ref>({});
const loading = ref(false);
const responseData = ref();
@@ -94,12 +98,21 @@ const formRules = computed(() => {
});
+
+
// 初始化表单数据
const initFormData = () => {
- formData.value = {}
- currentResource.value?.params.forEach(param => {
- formData.value[param.name] = param.type === 'number' ? 0 :
- param.type === 'boolean' ? false : ''
+ if (!currentResource.value?.params) return;
+
+ const newSchemaDataForm: Record = {};
+
+ currentResource.value.params.forEach(param => {
+ newSchemaDataForm[param.name] = getDefaultValue(param);
+ const originType = normaliseJavascriptType(typeof tabStorage.formData[param.name]);
+
+ if (tabStorage.formData[param.name]!== undefined && originType === param.type) {
+ newSchemaDataForm[param.name] = tabStorage.formData[param.name];
+ }
})
}
@@ -112,7 +125,7 @@ const resetForm = () => {
// 提交表单
function handleSubmit() {
const fillFn = currentResource.value.fill;
- const uri = fillFn(formData.value);
+ const uri = fillFn(tabStorage.formData);
const bridge = useMessageBridge();
diff --git a/renderer/src/components/main-panel/resource/resource-templates.vue b/renderer/src/components/main-panel/resource/resource-templates.vue
index 0ce8dee..757bb8d 100644
--- a/renderer/src/components/main-panel/resource/resource-templates.vue
+++ b/renderer/src/components/main-panel/resource/resource-templates.vue
@@ -64,7 +64,6 @@ function reloadResources(option: { first: boolean }) {
function handleClick(template: ResourceTemplate) {
tabStorage.currentResourceName = template.name;
- // TODO: 恢复这部分响应?
tabStorage.lastResourceReadResponse = undefined;
}
@@ -74,9 +73,9 @@ onMounted(() => {
commandCancel = bridge.addCommandListener('resources/templates/list', (data: CasualRestAPI) => {
resourcesManager.templates = data.msg.resourceTemplates || [];
- if (resourcesManager.templates.length > 0) {
+ const targetResource = resourcesManager.templates.find(template => template.name === tabStorage.currentResourceName);
+ if (targetResource === undefined) {
tabStorage.currentResourceName = resourcesManager.templates[0].name;
- // TODO: 恢复这部分响应?
tabStorage.lastResourceReadResponse = undefined;
}
}, { once: false });
diff --git a/renderer/src/components/main-panel/resource/resources.ts b/renderer/src/components/main-panel/resource/resources.ts
index 419ac62..2d6c81d 100644
--- a/renderer/src/components/main-panel/resource/resources.ts
+++ b/renderer/src/components/main-panel/resource/resources.ts
@@ -13,6 +13,7 @@ export const resourcesManager = reactive<{
export interface ResourceStorage {
currentResourceName: string;
lastResourceReadResponse?: ResourcesReadResponse;
+ formData: Record;
}
/**
@@ -22,7 +23,7 @@ export interface ResourceStorage {
*/
export function parseResourceTemplate(template: string): {
params: string[],
- fill: (params: Record) => string
+ fill: (params: Record) => string
} {
// 1. 提取所有参数名
const paramRegex = /\{([^}]+)\}/g;
@@ -36,7 +37,7 @@ export function parseResourceTemplate(template: string): {
const paramList = Array.from(params);
// 2. 创建填充函数
- const fill = (values: Record): string => {
+ const fill = (values: Record): string => {
let result = template;
// 验证所有必填参数
@@ -48,7 +49,7 @@ export function parseResourceTemplate(template: string): {
// 替换所有参数
for (const param of paramList) {
- result = result.replace(new RegExp(`\\{${param}\\}`, 'g'), values[param]);
+ result = result.replace(new RegExp(`\\{${param}\\}`, 'g'), values[param].toString());
}
return result;
diff --git a/renderer/src/components/main-panel/tool/tool-executor.vue b/renderer/src/components/main-panel/tool/tool-executor.vue
index d456b7d..d49dd95 100644
--- a/renderer/src/components/main-panel/tool/tool-executor.vue
+++ b/renderer/src/components/main-panel/tool/tool-executor.vue
@@ -54,6 +54,7 @@ import type { FormInstance, FormRules } from 'element-plus';
import { tabs } from '../panel';
import { callTool, toolsManager, ToolStorage } from './tools';
import { pinkLog } from '@/views/setting/util';
+import { getDefaultValue, normaliseJavascriptType } from '@/hook/mcp';
defineComponent({ name: 'tool-executor' });
@@ -99,15 +100,6 @@ const formRules = computed(() => {
return rules;
});
-const getDefaultValue = (property: any) => {
- if (property.type === 'number' || property.type === 'integer') {
- return 0;
- } else if (property.type === 'boolean') {
- return false;
- } else {
- return '';
- }
-};
const initFormData = () => {
// 初始化,根据输入的 inputSchema 校验
@@ -120,11 +112,8 @@ const initFormData = () => {
Object.entries(currentTool.value.inputSchema.properties).forEach(([name, property]) => {
newSchemaDataForm[name] = getDefaultValue(property);
- let originType: string = typeof tabStorage.formData[name];
- if (originType === 'number') {
- originType = 'integer';
- }
-
+ const originType = normaliseJavascriptType(typeof tabStorage.formData[name]);
+
if (tabStorage.formData[name] !== undefined && originType === property.type) {
newSchemaDataForm[name] = tabStorage.formData[name];
}
@@ -135,7 +124,6 @@ const initFormData = () => {
const resetForm = () => {
formRef.value?.resetFields();
- tabStorage.lastToolCallResponse = undefined;
};
async function handleExecute() {
diff --git a/renderer/src/hook/mcp.ts b/renderer/src/hook/mcp.ts
new file mode 100644
index 0000000..9e19f78
--- /dev/null
+++ b/renderer/src/hook/mcp.ts
@@ -0,0 +1,30 @@
+import { SchemaProperty } from "./type";
+
+interface TypeAble {
+ type: string;
+}
+
+export function getDefaultValue(property: TypeAble) {
+ if (property.type === 'number' || property.type === 'integer') {
+ return 0;
+ } else if (property.type === 'boolean') {
+ return false;
+ } else {
+ return '';
+ }
+}
+
+export function normaliseJavascriptType(type: string) {
+ switch (type) {
+ case 'integer':
+ return 'number';
+ case 'number':
+ return 'integer';
+ case 'boolean':
+ return 'boolean';
+ case 'string':
+ return 'string';
+ default:
+ return 'string';
+ }
+}
\ No newline at end of file
diff --git a/service/tabs.锦恢的 MCP Server.json b/service/tabs.锦恢的 MCP Server.json
index 5875047..a966a72 100644
--- a/service/tabs.锦恢的 MCP Server.json
+++ b/service/tabs.锦恢的 MCP Server.json
@@ -1,5 +1,5 @@
{
- "currentIndex": 1,
+ "currentIndex": 2,
"tabs": [
{
"name": "交互测试",
@@ -133,12 +133,33 @@
"content": [
{
"type": "text",
- "text": "CityWeather(city_name_en='hangzhou', city_name_cn='杭州', city_code='101210101', temp='20.7', wd='', ws='', sd='93%', aqi='13', weather='阴')"
+ "text": "CityWeather(city_name_en='hangzhou', city_name_cn='杭州', city_code='101210101', temp='20.3', wd='', ws='', sd='89%', aqi='38', weather='阴')"
}
],
"isError": false
}
}
+ },
+ {
+ "name": "资源",
+ "icon": "icon-file",
+ "type": "blank",
+ "componentIndex": 0,
+ "storage": {
+ "currentResourceName": "greeting",
+ "formData": {
+ "name": "kirigaya"
+ },
+ "lastResourceReadResponse": {
+ "contents": [
+ {
+ "uri": "greeting://kirigaya",
+ "mimeType": "text/plain",
+ "text": "Hello, kirigaya!"
+ }
+ ]
+ }
+ }
}
]
}
\ No newline at end of file