mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-24 18:50:56 +08:00
feat(mcp): mcp setting add service description page
This commit is contained in:
parent
317d452498
commit
696bf2dc79
@ -72,6 +72,7 @@
|
||||
"@langchain/community": "^0.3.36",
|
||||
"@mozilla/readability": "^0.6.0",
|
||||
"@notionhq/client": "^2.2.15",
|
||||
"@shikijs/markdown-it": "^3.2.2",
|
||||
"@strongtz/win32-arm64-msvc": "^0.4.7",
|
||||
"@tryfabric/martian": "^1.2.4",
|
||||
"@types/react-infinite-scroll-component": "^5.0.0",
|
||||
|
||||
@ -1121,6 +1121,7 @@
|
||||
"installHelp": "Get Installation Help",
|
||||
"tabs": {
|
||||
"general": "General",
|
||||
"description": "Description",
|
||||
"tools": "Tools",
|
||||
"prompts": "Prompts",
|
||||
"resources": "Resources"
|
||||
|
||||
@ -1120,6 +1120,7 @@
|
||||
"installHelp": "インストールヘルプを取得",
|
||||
"tabs": {
|
||||
"general": "一般",
|
||||
"description": "説明",
|
||||
"tools": "ツール",
|
||||
"prompts": "プロンプト",
|
||||
"resources": "リソース"
|
||||
|
||||
@ -1120,6 +1120,7 @@
|
||||
"installHelp": "Получить помощь по установке",
|
||||
"tabs": {
|
||||
"general": "Общие",
|
||||
"description": "Описание",
|
||||
"tools": "Инструменты",
|
||||
"prompts": "Подсказки",
|
||||
"resources": "Ресурсы"
|
||||
|
||||
@ -1121,6 +1121,7 @@
|
||||
"installHelp": "获取安装帮助",
|
||||
"tabs": {
|
||||
"general": "通用",
|
||||
"description": "描述",
|
||||
"tools": "工具",
|
||||
"prompts": "提示",
|
||||
"resources": "资源"
|
||||
|
||||
@ -1120,6 +1120,7 @@
|
||||
"installHelp": "獲取安裝幫助",
|
||||
"tabs": {
|
||||
"general": "通用",
|
||||
"description": "描述",
|
||||
"tools": "工具",
|
||||
"prompts": "提示",
|
||||
"resources": "資源"
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { getShikiInstance } from '@renderer/utils/shiki'
|
||||
import { Card } from 'antd'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import { npxFinder } from 'npx-scope-finder'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
interface McpDescriptionProps {
|
||||
searchKey: string
|
||||
}
|
||||
|
||||
const MCPDescription = ({ searchKey }: McpDescriptionProps) => {
|
||||
const [renderedMarkdown, setRenderedMarkdown] = useState('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const md = useRef<MarkdownIt>(
|
||||
new MarkdownIt({
|
||||
linkify: true, // 自动转换 URL 为链接
|
||||
typographer: true // 启用印刷格式优化
|
||||
})
|
||||
)
|
||||
const { theme } = useTheme()
|
||||
|
||||
useEffect(() => {
|
||||
const sk = getShikiInstance(theme)
|
||||
md.current.use(sk)
|
||||
getMcpInfo()
|
||||
}, [theme, searchKey])
|
||||
|
||||
const getMcpInfo = async () => {
|
||||
setLoading(true)
|
||||
const packages = await npxFinder(searchKey).finally(() => setLoading(false))
|
||||
const readme = packages[0]?.original?.readme ?? '暂无描述'
|
||||
setRenderedMarkdown(md.current.render(readme))
|
||||
}
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<Card loading={loading}>
|
||||
<div className="markdown" dangerouslySetInnerHTML={{ __html: renderedMarkdown }} />
|
||||
</Card>
|
||||
</Section>
|
||||
)
|
||||
}
|
||||
const Section = styled.div`
|
||||
padding-top: 8px;
|
||||
`
|
||||
|
||||
export default MCPDescription
|
||||
@ -1,6 +1,7 @@
|
||||
import { DeleteOutlined, SaveOutlined } from '@ant-design/icons'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import MCPDescription from '@renderer/pages/settings/MCPSettings/McpDescription'
|
||||
import { MCPPrompt, MCPResource, MCPServer, MCPTool } from '@renderer/types'
|
||||
import { Button, Flex, Form, Input, Radio, Switch, Tabs } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
@ -516,6 +517,13 @@ const McpSettings: React.FC = () => {
|
||||
)
|
||||
}
|
||||
]
|
||||
if (server.searchKey) {
|
||||
tabs.push({
|
||||
key: 'description',
|
||||
label: t('settings.mcp.tabs.description'),
|
||||
children: <MCPDescription searchKey={server.searchKey} />
|
||||
})
|
||||
}
|
||||
|
||||
if (server.isActive) {
|
||||
tabs.push(
|
||||
|
||||
@ -206,7 +206,8 @@ const NpxSearch: FC = () => {
|
||||
args: record.configSample?.args ?? ['-y', record.fullName],
|
||||
env: record.configSample?.env,
|
||||
isActive: false,
|
||||
type: record.type
|
||||
type: record.type,
|
||||
searchKey: record.fullName
|
||||
}
|
||||
|
||||
addMCPServer(newServer)
|
||||
|
||||
@ -403,6 +403,7 @@ export interface MCPServer {
|
||||
disabledTools?: string[] // List of tool names that are disabled for this server
|
||||
configSample?: MCPConfigSample
|
||||
headers?: Record<string, string> // Custom headers to be sent with requests to this server
|
||||
searchKey?: string
|
||||
}
|
||||
|
||||
export interface MCPToolInputSchema {
|
||||
|
||||
34
src/renderer/src/utils/shiki.ts
Normal file
34
src/renderer/src/utils/shiki.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { MarkdownItShikiOptions, setupMarkdownIt } from '@shikijs/markdown-it'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import { BuiltinLanguage, BuiltinTheme, bundledLanguages, createHighlighter } from 'shiki'
|
||||
|
||||
const defaultOptions = {
|
||||
themes: {
|
||||
light: 'one-light',
|
||||
dark: 'material-theme-darker'
|
||||
},
|
||||
defaultColor: 'light'
|
||||
}
|
||||
const initHighlighter = async (options: MarkdownItShikiOptions) => {
|
||||
const themeNames = ('themes' in options ? Object.values(options.themes) : [options.theme]).filter(
|
||||
Boolean
|
||||
) as BuiltinTheme[]
|
||||
return await createHighlighter({
|
||||
themes: themeNames,
|
||||
langs: options.langs || (Object.keys(bundledLanguages) as BuiltinLanguage[])
|
||||
})
|
||||
}
|
||||
|
||||
const highlighter = await initHighlighter(defaultOptions)
|
||||
|
||||
export function getShikiInstance(theme: ThemeMode) {
|
||||
const options = {
|
||||
...defaultOptions,
|
||||
defaultColor: theme
|
||||
}
|
||||
|
||||
return function (markdownit: MarkdownIt) {
|
||||
setupMarkdownIt(markdownit, highlighter, options)
|
||||
}
|
||||
}
|
||||
18
yarn.lock
18
yarn.lock
@ -3268,6 +3268,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@shikijs/markdown-it@npm:^3.2.2":
|
||||
version: 3.2.2
|
||||
resolution: "@shikijs/markdown-it@npm:3.2.2"
|
||||
dependencies:
|
||||
markdown-it: "npm:^14.1.0"
|
||||
shiki: "npm:3.2.2"
|
||||
peerDependencies:
|
||||
markdown-it-async: ^2.2.0
|
||||
peerDependenciesMeta:
|
||||
markdown-it-async:
|
||||
optional: true
|
||||
checksum: 10c0/37c98e45a0905ea58f605c7cd341c83f3289b6a37093862535c59f7cc178fe9bfb13413fea68d4d923341e51b2e5718fc5172147d15e07457a76aceed2ac1f95
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@shikijs/themes@npm:3.2.2":
|
||||
version: 3.2.2
|
||||
resolution: "@shikijs/themes@npm:3.2.2"
|
||||
@ -4315,6 +4330,7 @@ __metadata:
|
||||
"@mozilla/readability": "npm:^0.6.0"
|
||||
"@notionhq/client": "npm:^2.2.15"
|
||||
"@reduxjs/toolkit": "npm:^2.2.5"
|
||||
"@shikijs/markdown-it": "npm:^3.2.2"
|
||||
"@strongtz/win32-arm64-msvc": "npm:^0.4.7"
|
||||
"@swc/plugin-styled-components": "npm:^7.1.3"
|
||||
"@tavily/core": "patch:@tavily/core@npm%3A0.3.1#~/.yarn/patches/@tavily-core-npm-0.3.1-fe69bf2bea.patch"
|
||||
@ -15553,7 +15569,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"shiki@npm:^3.2.1":
|
||||
"shiki@npm:3.2.2, shiki@npm:^3.2.1":
|
||||
version: 3.2.2
|
||||
resolution: "shiki@npm:3.2.2"
|
||||
dependencies:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user