mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-29 14:31:35 +08:00
fix(MCP): add missing /mcp suffix to TokenFlux sync URLs (#8777)
This commit is contained in:
parent
c52bb47fef
commit
82923a7c64
@ -6,9 +6,9 @@ import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { getModelScopeToken, saveModelScopeToken, syncModelScopeServers } from './modelscopeSyncUtils'
|
||||
import { getAI302Token, saveAI302Token, syncAi302Servers } from './providers/302ai'
|
||||
import { getTokenLanYunToken, LANYUN_KEY_HOST, saveTokenLanYunToken, syncTokenLanYunServers } from './providers/lanyun'
|
||||
import { getModelScopeToken, MODELSCOPE_HOST, saveModelScopeToken, syncModelScopeServers } from './providers/modelscope'
|
||||
import { getTokenFluxToken, saveTokenFluxToken, syncTokenFluxServers, TOKENFLUX_HOST } from './providers/tokenflux'
|
||||
|
||||
// Provider configuration interface
|
||||
@ -30,8 +30,8 @@ const providers: ProviderConfig[] = [
|
||||
key: 'modelscope',
|
||||
name: 'ModelScope',
|
||||
description: 'ModelScope 平台 MCP 服务',
|
||||
discoverUrl: 'https://www.modelscope.cn/mcp?hosted=1&page=1',
|
||||
apiKeyUrl: 'https://www.modelscope.cn/my/myaccesstoken',
|
||||
discoverUrl: `${MODELSCOPE_HOST}/mcp?hosted=1&page=1`,
|
||||
apiKeyUrl: `${MODELSCOPE_HOST}/my/myaccesstoken`,
|
||||
tokenFieldName: 'modelScopeToken',
|
||||
getToken: getModelScopeToken,
|
||||
saveToken: saveModelScopeToken,
|
||||
@ -78,7 +78,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const PopupContainer: React.FC<Props> = ({ resolve, existingServers }) => {
|
||||
const { addMCPServer } = useMCPServers()
|
||||
const { addMCPServer, updateMCPServer } = useMCPServers()
|
||||
const [open, setOpen] = useState(true)
|
||||
const [isSyncing, setIsSyncing] = useState(false)
|
||||
const [selectedProviderKey, setSelectedProviderKey] = useState(providers[0].key)
|
||||
@ -128,11 +128,18 @@ const PopupContainer: React.FC<Props> = ({ resolve, existingServers }) => {
|
||||
// Sync servers
|
||||
const result = await selectedProvider.syncServers(token, existingServers)
|
||||
|
||||
if (result.success && result.addedServers?.length > 0) {
|
||||
// Add the new servers to the store
|
||||
if (result.success && (result.addedServers?.length > 0 || (result as any).updatedServers?.length > 0)) {
|
||||
// Add new servers to the store
|
||||
for (const server of result.addedServers) {
|
||||
addMCPServer(server)
|
||||
}
|
||||
// Update existing servers with latest info
|
||||
const updatedServers = (result as any).updatedServers
|
||||
if (updatedServers?.length > 0) {
|
||||
for (const server of updatedServers) {
|
||||
updateMCPServer(server)
|
||||
}
|
||||
}
|
||||
window.message.success(result.message)
|
||||
setOpen(false)
|
||||
} else {
|
||||
@ -148,7 +155,7 @@ const PopupContainer: React.FC<Props> = ({ resolve, existingServers }) => {
|
||||
} finally {
|
||||
setIsSyncing(false)
|
||||
}
|
||||
}, [addMCPServer, existingServers, form, selectedProvider, t])
|
||||
}, [addMCPServer, updateMCPServer, existingServers, form, selectedProvider, t])
|
||||
|
||||
const onCancel = () => {
|
||||
setOpen(false)
|
||||
|
||||
@ -29,6 +29,7 @@ interface Ai302SyncResult {
|
||||
success: boolean
|
||||
message: string
|
||||
addedServers: MCPServer[]
|
||||
updatedServers: MCPServer[]
|
||||
errorDetails?: string
|
||||
}
|
||||
|
||||
@ -51,7 +52,8 @@ export const syncAi302Servers = async (token: string, existingServers: MCPServer
|
||||
return {
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.unauthorized', 'Sync Unauthorized'),
|
||||
addedServers: []
|
||||
addedServers: [],
|
||||
updatedServers: []
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +63,7 @@ export const syncAi302Servers = async (token: string, existingServers: MCPServer
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.error'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: `Status: ${response.status}`
|
||||
}
|
||||
}
|
||||
@ -74,17 +77,20 @@ export const syncAi302Servers = async (token: string, existingServers: MCPServer
|
||||
return {
|
||||
success: true,
|
||||
message: t('settings.mcp.sync.noServersAvailable', 'No MCP servers available'),
|
||||
addedServers: []
|
||||
addedServers: [],
|
||||
updatedServers: []
|
||||
}
|
||||
}
|
||||
|
||||
// Transform TokenFlux servers to MCP servers format
|
||||
// Transform 302ai servers to MCP servers format
|
||||
const addedServers: MCPServer[] = []
|
||||
const updatedServers: MCPServer[] = []
|
||||
|
||||
for (const server of servers) {
|
||||
try {
|
||||
// Skip if server already exists
|
||||
if (existingServers.some((s) => s.id === `@302ai/${server.name}`)) continue
|
||||
// Check if server already exists
|
||||
const existingServer = existingServers.find((s) => s.id === `@302ai/${server.name}`)
|
||||
|
||||
const mcpServer: MCPServer = {
|
||||
id: `@302ai/${server.name}`,
|
||||
name: server.name || `302ai Server ${nanoid()}`,
|
||||
@ -98,16 +104,24 @@ export const syncAi302Servers = async (token: string, existingServers: MCPServer
|
||||
logoUrl: server.logoUrl
|
||||
}
|
||||
|
||||
addedServers.push(mcpServer)
|
||||
if (existingServer) {
|
||||
// Update existing server with latest info
|
||||
updatedServers.push(mcpServer)
|
||||
} else {
|
||||
// Add new server
|
||||
addedServers.push(mcpServer)
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Error processing 302ai server:', err as Error)
|
||||
}
|
||||
}
|
||||
|
||||
const totalServers = addedServers.length + updatedServers.length
|
||||
return {
|
||||
success: true,
|
||||
message: t('settings.mcp.sync.success', { count: addedServers.length }),
|
||||
addedServers
|
||||
message: t('settings.mcp.sync.success', { count: totalServers }),
|
||||
addedServers,
|
||||
updatedServers
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('302ai sync error:', error as Error)
|
||||
@ -115,6 +129,7 @@ export const syncAi302Servers = async (token: string, existingServers: MCPServer
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.error'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: String(error)
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ interface TokenLanYunSyncResult {
|
||||
success: boolean
|
||||
message: string
|
||||
addedServers: MCPServer[]
|
||||
updatedServers: MCPServer[]
|
||||
errorDetails?: string
|
||||
}
|
||||
|
||||
@ -80,7 +81,8 @@ export const syncTokenLanYunServers = async (
|
||||
return {
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.unauthorized', 'Sync Unauthorized'),
|
||||
addedServers: []
|
||||
addedServers: [],
|
||||
updatedServers: []
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,6 +92,7 @@ export const syncTokenLanYunServers = async (
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.error'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: `Status: ${response.status}`
|
||||
}
|
||||
}
|
||||
@ -101,6 +104,7 @@ export const syncTokenLanYunServers = async (
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.unauthorized', 'Sync Unauthorized'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: `Status: ${response.status}`
|
||||
}
|
||||
}
|
||||
@ -109,6 +113,7 @@ export const syncTokenLanYunServers = async (
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.error'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: `Status: ${response.status}`
|
||||
}
|
||||
}
|
||||
@ -119,27 +124,21 @@ export const syncTokenLanYunServers = async (
|
||||
return {
|
||||
success: true,
|
||||
message: t('settings.mcp.sync.noServersAvailable', 'No MCP servers available'),
|
||||
addedServers: []
|
||||
addedServers: [],
|
||||
updatedServers: []
|
||||
}
|
||||
}
|
||||
|
||||
// Transform Token servers to MCP servers format
|
||||
const addedServers: MCPServer[] = []
|
||||
const updatedServers: MCPServer[] = []
|
||||
logger.debug('TokenLanYun servers:', servers)
|
||||
for (const server of servers) {
|
||||
try {
|
||||
if (!server.operationalUrls?.[0]?.url) continue
|
||||
|
||||
// If any existing server id contains '@lanyun', clear them before adding new ones
|
||||
// if (existingServers.some((s) => s.id.startsWith('@lanyun'))) {
|
||||
// for (let i = existingServers.length - 1; i >= 0; i--) {
|
||||
// if (existingServers[i].id.startsWith('@lanyun')) {
|
||||
// existingServers.splice(i, 1)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Skip if server already exists after clearing
|
||||
if (existingServers.some((s) => s.id === `@lanyun/${server.id}`)) continue
|
||||
// Check if server already exists
|
||||
const existingServer = existingServers.find((s) => s.id === `@lanyun/${server.id}`)
|
||||
|
||||
const mcpServer: MCPServer = {
|
||||
id: `@lanyun/${server.id}`,
|
||||
@ -158,16 +157,24 @@ export const syncTokenLanYunServers = async (
|
||||
tags: server.tags ?? (server.chineseName ? [server.chineseName] : [])
|
||||
}
|
||||
|
||||
addedServers.push(mcpServer)
|
||||
if (existingServer) {
|
||||
// Update existing server with latest info
|
||||
updatedServers.push(mcpServer)
|
||||
} else {
|
||||
// Add new server
|
||||
addedServers.push(mcpServer)
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Error processing LanYun server:', err as Error)
|
||||
}
|
||||
}
|
||||
|
||||
const totalServers = addedServers.length + updatedServers.length
|
||||
return {
|
||||
success: true,
|
||||
message: t('settings.mcp.sync.success', { count: addedServers.length }),
|
||||
addedServers
|
||||
message: t('settings.mcp.sync.success', { count: totalServers }),
|
||||
addedServers,
|
||||
updatedServers
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('TokenLanyun sync error:', error as Error)
|
||||
@ -175,6 +182,7 @@ export const syncTokenLanYunServers = async (
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.error'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: String(error)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { loggerService } from '@logger'
|
||||
import { nanoid } from '@reduxjs/toolkit'
|
||||
import { MCPServer } from '@renderer/types'
|
||||
import type { MCPServer } from '@renderer/types'
|
||||
import i18next from 'i18next'
|
||||
|
||||
const logger = loggerService.withContext('ModelScopeSyncUtils')
|
||||
|
||||
// Token storage constants and utilities
|
||||
const TOKEN_STORAGE_KEY = 'modelscope_token'
|
||||
export const MODELSCOPE_HOST = 'https://www.modelscope.cn'
|
||||
|
||||
export const saveModelScopeToken = (token: string): void => {
|
||||
localStorage.setItem(TOKEN_STORAGE_KEY, token)
|
||||
@ -38,6 +39,7 @@ interface ModelScopeSyncResult {
|
||||
success: boolean
|
||||
message: string
|
||||
addedServers: MCPServer[]
|
||||
updatedServers: MCPServer[]
|
||||
errorDetails?: string
|
||||
}
|
||||
|
||||
@ -49,7 +51,7 @@ export const syncModelScopeServers = async (
|
||||
const t = i18next.t
|
||||
|
||||
try {
|
||||
const response = await fetch('https://www.modelscope.cn/api/v1/mcp/services/operational', {
|
||||
const response = await fetch(`${MODELSCOPE_HOST}/api/v1/mcp/services/operational`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@ -63,7 +65,8 @@ export const syncModelScopeServers = async (
|
||||
return {
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.unauthorized', 'Sync Unauthorized'),
|
||||
addedServers: []
|
||||
addedServers: [],
|
||||
updatedServers: []
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,6 +76,7 @@ export const syncModelScopeServers = async (
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.error'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: `Status: ${response.status}`
|
||||
}
|
||||
}
|
||||
@ -85,19 +89,21 @@ export const syncModelScopeServers = async (
|
||||
return {
|
||||
success: true,
|
||||
message: t('settings.mcp.sync.noServersAvailable', 'No MCP servers available'),
|
||||
addedServers: []
|
||||
addedServers: [],
|
||||
updatedServers: []
|
||||
}
|
||||
}
|
||||
|
||||
// Transform ModelScope servers to MCP servers format
|
||||
const addedServers: MCPServer[] = []
|
||||
const updatedServers: MCPServer[] = []
|
||||
|
||||
for (const server of servers) {
|
||||
try {
|
||||
if (!server.operational_urls?.[0]?.url) continue
|
||||
|
||||
// Skip if server already exists
|
||||
if (existingServers.some((s) => s.id === `@modelscope/${server.id}`)) continue
|
||||
// Check if server already exists
|
||||
const existingServer = existingServers.find((s) => s.id === `@modelscope/${server.id}`)
|
||||
|
||||
const mcpServer: MCPServer = {
|
||||
id: `@modelscope/${server.id}`,
|
||||
@ -110,21 +116,29 @@ export const syncModelScopeServers = async (
|
||||
env: {},
|
||||
isActive: true,
|
||||
provider: 'ModelScope',
|
||||
providerUrl: `https://www.modelscope.cn/mcp/servers/@${server.id}`,
|
||||
providerUrl: `${MODELSCOPE_HOST}/mcp/servers/@${server.id}`,
|
||||
logoUrl: server.logo_url || '',
|
||||
tags: server.tags || []
|
||||
}
|
||||
|
||||
addedServers.push(mcpServer)
|
||||
if (existingServer) {
|
||||
// Update existing server with latest info
|
||||
updatedServers.push(mcpServer)
|
||||
} else {
|
||||
// Add new server
|
||||
addedServers.push(mcpServer)
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Error processing ModelScope server:', err as Error)
|
||||
}
|
||||
}
|
||||
|
||||
const totalServers = addedServers.length + updatedServers.length
|
||||
return {
|
||||
success: true,
|
||||
message: t('settings.mcp.sync.success', { count: addedServers.length }),
|
||||
addedServers
|
||||
message: t('settings.mcp.sync.success', { count: totalServers }),
|
||||
addedServers,
|
||||
updatedServers
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('ModelScope sync error:', error as Error)
|
||||
@ -132,6 +146,7 @@ export const syncModelScopeServers = async (
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.error'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: String(error)
|
||||
}
|
||||
}
|
||||
@ -45,6 +45,7 @@ interface TokenFluxSyncResult {
|
||||
success: boolean
|
||||
message: string
|
||||
addedServers: MCPServer[]
|
||||
updatedServers: MCPServer[]
|
||||
errorDetails?: string
|
||||
}
|
||||
|
||||
@ -70,7 +71,8 @@ export const syncTokenFluxServers = async (
|
||||
return {
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.unauthorized', 'Sync Unauthorized'),
|
||||
addedServers: []
|
||||
addedServers: [],
|
||||
updatedServers: []
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,6 +82,7 @@ export const syncTokenFluxServers = async (
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.error'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: `Status: ${response.status}`
|
||||
}
|
||||
}
|
||||
@ -92,17 +95,19 @@ export const syncTokenFluxServers = async (
|
||||
return {
|
||||
success: true,
|
||||
message: t('settings.mcp.sync.noServersAvailable', 'No MCP servers available'),
|
||||
addedServers: []
|
||||
addedServers: [],
|
||||
updatedServers: []
|
||||
}
|
||||
}
|
||||
|
||||
// Transform TokenFlux servers to MCP servers format
|
||||
const addedServers: MCPServer[] = []
|
||||
const updatedServers: MCPServer[] = []
|
||||
|
||||
for (const server of servers) {
|
||||
try {
|
||||
// Skip if server already exists
|
||||
if (existingServers.some((s) => s.id === `@tokenflux/${server.name}`)) continue
|
||||
// Check if server already exists
|
||||
const existingServer = existingServers.find((s) => s.id === `@tokenflux/${server.name}`)
|
||||
|
||||
const authHeaders = {}
|
||||
if (server.security_schemes && server.security_schemes.api_key) {
|
||||
@ -117,7 +122,7 @@ export const syncTokenFluxServers = async (
|
||||
name: server.display_name || server.name || `TokenFlux Server ${nanoid()}`,
|
||||
description: server.description || '',
|
||||
type: 'streamableHttp',
|
||||
baseUrl: `${TOKENFLUX_HOST}/v1/mcps/${server.name}`,
|
||||
baseUrl: `${TOKENFLUX_HOST}/v1/mcps/${server.name}/mcp`,
|
||||
isActive: true,
|
||||
provider: 'TokenFlux',
|
||||
providerUrl: `${TOKENFLUX_HOST}/mcps/${server.name}`,
|
||||
@ -126,16 +131,24 @@ export const syncTokenFluxServers = async (
|
||||
headers: authHeaders
|
||||
}
|
||||
|
||||
addedServers.push(mcpServer)
|
||||
if (existingServer) {
|
||||
// Update existing server with corrected URL and latest info
|
||||
updatedServers.push(mcpServer)
|
||||
} else {
|
||||
// Add new server
|
||||
addedServers.push(mcpServer)
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Error processing TokenFlux server:', err as Error)
|
||||
}
|
||||
}
|
||||
|
||||
const totalServers = addedServers.length + updatedServers.length
|
||||
return {
|
||||
success: true,
|
||||
message: t('settings.mcp.sync.success', { count: addedServers.length }),
|
||||
addedServers
|
||||
message: t('settings.mcp.sync.success', { count: totalServers }),
|
||||
addedServers,
|
||||
updatedServers
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('TokenFlux sync error:', error as Error)
|
||||
@ -143,6 +156,7 @@ export const syncTokenFluxServers = async (
|
||||
success: false,
|
||||
message: t('settings.mcp.sync.error'),
|
||||
addedServers: [],
|
||||
updatedServers: [],
|
||||
errorDetails: String(error)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user