feat: add support for 302AI provider in MCP settings (#7755)

* feat: add support for 302AI provider in MCP settings

- Introduced new provider for 302AI, including token management and server synchronization functionality.
- Updated SyncServersPopup to integrate 302AI provider.
- Added new file for 302AI provider utilities, including token storage and server fetching logic.

* fix: re-merge main
This commit is contained in:
⌞L⌝ 2025-07-16 17:40:30 +08:00 committed by GitHub
parent 3132150fb8
commit f0d86cbaec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 130 additions and 0 deletions

View File

@ -7,6 +7,7 @@ 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 { getTokenFluxToken, saveTokenFluxToken, syncTokenFluxServers, TOKENFLUX_HOST } from './providers/tokenflux'
@ -57,6 +58,17 @@ const providers: ProviderConfig[] = [
getToken: getTokenLanYunToken,
saveToken: saveTokenLanYunToken,
syncServers: syncTokenLanYunServers
},
{
key: '302ai',
name: '302AI',
description: '302AI 平台 MCP 服务',
discoverUrl: 'https://302.ai',
apiKeyUrl: 'https://dash.302.ai/apis/list',
tokenFieldName: 'token302aiToken',
getToken: getAI302Token,
saveToken: saveAI302Token,
syncServers: syncAi302Servers
}
]

View File

@ -0,0 +1,118 @@
import { nanoid } from '@reduxjs/toolkit'
import type { MCPServer } from '@renderer/types'
import i18next from 'i18next'
// Token storage constants and utilities
const TOKEN_STORAGE_KEY = 'ai302_token'
export const AI302_HOST = 'https://api.302.ai/mcp'
export const saveAI302Token = (token: string): void => {
localStorage.setItem(TOKEN_STORAGE_KEY, token)
}
export const getAI302Token = (): string | null => {
return localStorage.getItem(TOKEN_STORAGE_KEY)
}
export const clearAI302Token = (): void => {
localStorage.removeItem(TOKEN_STORAGE_KEY)
}
export const hasAI302Token = (): boolean => {
return !!getAI302Token()
}
interface Ai302SyncResult {
success: boolean
message: string
addedServers: MCPServer[]
errorDetails?: string
}
// Function to fetch and process 302ai servers
export const syncAi302Servers = async (token: string, existingServers: MCPServer[]): Promise<Ai302SyncResult> => {
const t = i18next.t
try {
const response = await fetch(`${AI302_HOST}/v1/mcps/list?baseUrl=https://api.302.ai/custom-mcp/mcp`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'x-api-key': token
}
})
// Handle authentication errors
if (response.status === 401 || response.status === 403) {
clearAI302Token()
return {
success: false,
message: t('settings.mcp.sync.unauthorized', 'Sync Unauthorized'),
addedServers: []
}
}
// Handle server errors
if (response.status === 500 || !response.ok) {
return {
success: false,
message: t('settings.mcp.sync.error'),
addedServers: [],
errorDetails: `Status: ${response.status}`
}
}
// Process successful response
const data = await response.json()
const servers: MCPServer[] = data.mcps || []
console.log('servers', servers)
if (servers.length === 0) {
return {
success: true,
message: t('settings.mcp.sync.noServersAvailable', 'No MCP servers available'),
addedServers: []
}
}
// Transform TokenFlux servers to MCP servers format
const addedServers: MCPServer[] = []
for (const server of servers) {
try {
// Skip if server already exists
if (existingServers.some((s) => s.id === `@302ai/${server.name}`)) continue
const mcpServer: MCPServer = {
id: `@302ai/${server.name}`,
name: server.name || `302ai Server ${nanoid()}`,
description: server.description || '',
type: server.type,
baseUrl: server.baseUrl,
isActive: server.isActive,
provider: server.provider,
providerUrl: server.providerUrl,
tags: server.tags,
logoUrl: server.logoUrl
}
addedServers.push(mcpServer)
} catch (err) {
console.error('Error processing 302ai server:', err)
}
}
return {
success: true,
message: t('settings.mcp.sync.success', { count: addedServers.length }),
addedServers
}
} catch (error) {
console.error('302ai sync error:', error)
return {
success: false,
message: t('settings.mcp.sync.error'),
addedServers: [],
errorDetails: String(error)
}
}
}