mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-12 00:49:14 +08:00
* feat(mcp): add hub server type definitions
- Add 'hub' to BuiltinMCPServerNames enum as '@cherry/hub'
- Create GeneratedTool, SearchQuery, ExecInput, ExecOutput types
- Add ExecutionContext and ConsoleMethods interfaces
Amp-Thread-ID: https://ampcode.com/threads/T-019b4e7d-86a3-770d-82f8-9e646e7e597e
Co-authored-by: Amp <amp@ampcode.com>
* feat(mcp): implement hub server core components
- generator.ts: Convert MCP tools to JS functions with JSDoc
- tool-registry.ts: In-memory cache with 10-min TTL
- search.ts: Comma-separated keyword search with ranking
- runtime.ts: Code execution with parallel/settle/console helpers
Amp-Thread-ID: https://ampcode.com/threads/T-019b4e7d-86a3-770d-82f8-9e646e7e597e
Co-authored-by: Amp <amp@ampcode.com>
* feat(mcp): integrate hub server with MCP infrastructure
- Create HubServer class with search/exec tools
- Implement mcp-bridge for calling tools via MCPService
- Register hub server in factory with dependency injection
- Initialize hub dependencies in MCPService constructor
- Add hub server description label for i18n
Amp-Thread-ID: https://ampcode.com/threads/T-019b4e7d-86a3-770d-82f8-9e646e7e597e
Co-authored-by: Amp <amp@ampcode.com>
* test(mcp): add unit tests for hub server
- generator.test.ts: Test schema conversion and JSDoc generation
- search.test.ts: Test keyword matching, ranking, and limits
- runtime.test.ts: Test code execution, helpers, and error handling
Amp-Thread-ID: https://ampcode.com/threads/T-019b4e7d-86a3-770d-82f8-9e646e7e597e
Co-authored-by: Amp <amp@ampcode.com>
* docs(mcp): add hub server documentation
- Document search/exec tool usage and parameters
- Explain configuration and caching behavior
- Include architecture diagram and file structure
Amp-Thread-ID: https://ampcode.com/threads/T-019b4e7d-86a3-770d-82f8-9e646e7e597e
Co-authored-by: Amp <amp@ampcode.com>
* ♻️ refactor(hub): simplify dependency injection for HubServer
- Remove HubServerDependencies interface and setHubServerDependencies from factory
- Add initHubBridge() to mcp-bridge for direct initialization
- Make HubServer constructor parameterless (uses pre-initialized bridge)
- MCPService now calls initHubBridge() directly instead of factory setter
- Add integration tests for full search → exec flow
* 📝 docs(hub): add comments explaining why hub is not in builtin list
- Add JSDoc to HubServer class explaining its purpose and design
- Add comment to builtinMCPServers explaining hub exclusion
- Hub is a meta-server for LLM code mode, auto-enabled internally
* ✨ feat: add available tools section to HUB_MODE_SYSTEM_PROMPT
- Add shared utility for generating MCP tool function names (serverName_toolName format)
- Update hub server to use consistent function naming across search, exec and prompt
- Add fetchAllActiveServerTools to ApiService for renderer process
- Update parameterBuilder to include available tools in auto/hub mode prompt
- Use CacheService for 1-minute tools caching in hub server
- Remove ToolRegistry in favor of direct fetching with caching
- Update search ranking to include server name matching
- Fix tests to use new naming format
Amp-Thread-ID: https://ampcode.com/threads/T-019b6971-d5c9-7719-9245-a89390078647
Co-authored-by: Amp <amp@ampcode.com>
* ♻️ refactor: consolidate MCP tool name utilities into shared module
- Merge buildFunctionCallToolName from src/main/utils/mcp.ts into packages/shared/mcp.ts
- Create unified buildMcpToolName base function with options for prefix, delimiter, maxLength, existingNames
- Fix toCamelCase to normalize uppercase snake case (MY_SERVER → myServer)
- Fix maxLength + existingNames interaction to respect length limit when adding collision suffix
- Add comprehensive JSDoc documentation
- Update tests and hub.test.ts for new lowercase normalization behavior
* ✨ feat: isolate hub exec worker and filter disabled tools
* 🐛 fix: inline hub worker source
* 🐛 fix: sync hub tool cache and map
* Update import path for buildFunctionCallToolName in BaseService
* ✨ feat: refine hub mode system prompt
* 🐛 fix: propagate hub tool errors
* 📝 docs: clarify hub exec return
* ✨ feat(hub): improve prompts and tool descriptions for better LLM success rate
- Rewrite HUB_MODE_SYSTEM_PROMPT_BASE with Critical Rules section
- Add Common Mistakes to Avoid section with examples
- Update exec tool description with IMPORTANT return requirement
- Improve search tool description clarity
- Simplify generator output with return reminder in header
- Add per-field @param JSDoc with required/optional markers
Fixes issue where LLMs forgot to return values from exec code
* ♻️ refactor(hub): return empty string when no tools available
* ✨ feat(hub): add dedicated AUTO_MODE_SYSTEM_PROMPT for auto mode
- Create self-contained prompt teaching XML tool_use format
- Only shows search/exec tools (no generic examples)
- Add complete workflow example with common mistakes
- Update parameterBuilder to use getAutoModeSystemPrompt()
- User prompt comes first, then auto mode instructions
- Skip hub prompt when no tools available
* ♻️ refactor: move hub prompts to dedicated prompts-code-mode.ts
- Create src/renderer/src/config/prompts-code-mode.ts
- Move HUB_MODE_SYSTEM_PROMPT_BASE and AUTO_MODE_SYSTEM_PROMPT_BASE
- Move getHubModeSystemPrompt() and getAutoModeSystemPrompt()
- Extract shared buildToolsSection() helper
- Update parameterBuilder.ts import
* ♻️ refactor: add mcpMode support to promptToolUsePlugin
- Add mcpMode parameter to PromptToolUseConfig and defaultBuildSystemPrompt
- Pass mcpMode through middleware config to plugin builder
- Consolidate getAutoModeSystemPrompt into getHubModeSystemPrompt
- Update parameterBuilder to use getHubModeSystemPrompt
* ♻️ refactor: move getHubModeSystemPrompt to shared package
- Create @cherrystudio/shared workspace package with exports
- Move getHubModeSystemPrompt and ToolInfo to packages/shared/prompts
- Add @cherrystudio/shared dependency to @cherrystudio/ai-core
- Update promptToolUsePlugin to import from shared package
- Update renderer prompts-code-mode.ts to re-export from shared
- Add toolSetToToolInfoArray converter for type compatibility
* Revert "♻️ refactor: move getHubModeSystemPrompt to shared package"
This reverts commit 894b2fd487.
* Remove duplicate Tool Use Examples header from system prompt
* fix: add handleModeChange call in MCPToolsButton for manual mode activation
* style: update AssistantMCPSettings to use min-height instead of overflow for better layout control
* feat(i18n): add MCP server modes and truncate messages in multiple languages
- Introduced new "mode" options for MCP servers: auto, disabled, and manual with corresponding descriptions and labels.
- Added translations for "base64DataTruncated" and "truncated" messages across various language files.
- Enhanced user experience by providing clearer feedback on data truncation.
* Normalize tool names for search and exec in parser
* Clarify tool usage rules in code mode prompts and examples
* Clarify code execution instructions and update example usage
* refactor: simplify JSDoc description handling by removing unnecessary truncation
* refactor: optimize listAllActiveServerTools method to use Promise.allSettled for improved error handling and performance
---------
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
76 lines
2.1 KiB
TypeScript
76 lines
2.1 KiB
TypeScript
import type { MCPServer, MCPTool } from '@types'
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
vi.mock('@main/apiServer/utils/mcp', () => ({
|
|
getMCPServersFromRedux: vi.fn()
|
|
}))
|
|
|
|
vi.mock('@main/services/WindowService', () => ({
|
|
windowService: {
|
|
getMainWindow: vi.fn(() => null)
|
|
}
|
|
}))
|
|
|
|
import { getMCPServersFromRedux } from '@main/apiServer/utils/mcp'
|
|
import mcpService from '@main/services/MCPService'
|
|
|
|
const baseInputSchema: { type: 'object'; properties: Record<string, unknown>; required: string[] } = {
|
|
type: 'object',
|
|
properties: {},
|
|
required: []
|
|
}
|
|
|
|
const createTool = (overrides: Partial<MCPTool>): MCPTool => ({
|
|
id: `${overrides.serverId}__${overrides.name}`,
|
|
name: overrides.name ?? 'tool',
|
|
description: overrides.description,
|
|
serverId: overrides.serverId ?? 'server',
|
|
serverName: overrides.serverName ?? 'server',
|
|
inputSchema: baseInputSchema,
|
|
type: 'mcp',
|
|
...overrides
|
|
})
|
|
|
|
describe('MCPService.listAllActiveServerTools', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
it('filters disabled tools per server', async () => {
|
|
const servers: MCPServer[] = [
|
|
{
|
|
id: 'alpha',
|
|
name: 'Alpha',
|
|
isActive: true,
|
|
disabledTools: ['disabled_tool']
|
|
},
|
|
{
|
|
id: 'beta',
|
|
name: 'Beta',
|
|
isActive: true
|
|
}
|
|
]
|
|
|
|
vi.mocked(getMCPServersFromRedux).mockResolvedValue(servers)
|
|
|
|
const listToolsSpy = vi.spyOn(mcpService as any, 'listToolsImpl').mockImplementation(async (server: any) => {
|
|
if (server.id === 'alpha') {
|
|
return [
|
|
createTool({ name: 'enabled_tool', serverId: server.id, serverName: server.name }),
|
|
createTool({ name: 'disabled_tool', serverId: server.id, serverName: server.name })
|
|
]
|
|
}
|
|
return [createTool({ name: 'beta_tool', serverId: server.id, serverName: server.name })]
|
|
})
|
|
|
|
const tools = await mcpService.listAllActiveServerTools()
|
|
|
|
expect(listToolsSpy).toHaveBeenCalledTimes(2)
|
|
expect(tools.map((tool) => tool.name)).toEqual(['enabled_tool', 'beta_tool'])
|
|
})
|
|
})
|