Add embedded MCP server with shared API facade

This commit is contained in:
影烨
2026-03-23 23:53:54 +08:00
parent 72813c24d9
commit fe130caf4b
16 changed files with 2311 additions and 377 deletions
+57
View File
@@ -111,6 +111,10 @@ interface AISummarySettingsProps {
setEnableThinking: (val: boolean) => void
messageLimit: number
setMessageLimit: (val: number) => void
mcpEnabled: boolean
setMcpEnabled: (val: boolean) => void
mcpExposeMediaPaths: boolean
setMcpExposeMediaPaths: (val: boolean) => void
showMessage: (text: string, success: boolean) => void
}
@@ -133,6 +137,10 @@ function AISummarySettings({
setEnableThinking,
messageLimit,
setMessageLimit,
mcpEnabled,
setMcpEnabled,
mcpExposeMediaPaths,
setMcpExposeMediaPaths,
showMessage
}: AISummarySettingsProps) {
const [showApiKey, setShowApiKey] = useState(false)
@@ -750,6 +758,55 @@ function AISummarySettings({
</>
)}
<h3 className="section-title">MCP Server</h3>
<div className="settings-form" style={{ marginTop: '8px' }}>
<div className="form-group">
<label className="toggle-label">
<div className="toggle-header">
<span className="toggle-title"> MCP Server</span>
<span className="toggle-switch">
<input
type="checkbox"
checked={mcpEnabled}
onChange={(e) => setMcpEnabled(e.target.checked)}
/>
<span className="toggle-slider"></span>
</span>
</div>
</label>
<div className="toggle-description">
<p> Claude DesktopCodexCherry Studio MCP 宿 CipherTalk </p>
</div>
</div>
<div className="form-group">
<label className="toggle-label">
<div className="toggle-header">
<span className="toggle-title"></span>
<span className="toggle-switch">
<input
type="checkbox"
checked={mcpExposeMediaPaths}
onChange={(e) => setMcpExposeMediaPaths(e.target.checked)}
/>
<span className="toggle-slider"></span>
</span>
</div>
</label>
<div className="toggle-description">
<p> MCP `get_messages` </p>
</div>
</div>
<div className="form-group">
<label></label>
<input className="api-key-input" type="text" value="npm run build:mcp && node scripts/mcp-runner.js" readOnly />
<div className="form-hint">
`health_check``get_status``list_sessions``get_messages``list_contacts`
</div>
</div>
</div>
<div className="info-box-simple">
<p>💡 API </p>
</div>
+19
View File
@@ -140,6 +140,8 @@ function SettingsPage() {
const [aiCustomSystemPrompt, setAiCustomSystemPromptState] = useState<string>('')
const [aiEnableThinking, setAiEnableThinkingState] = useState<boolean>(true)
const [aiMessageLimit, setAiMessageLimitState] = useState<number>(3000)
const [mcpEnabled, setMcpEnabledState] = useState<boolean>(false)
const [mcpExposeMediaPaths, setMcpExposeMediaPathsState] = useState<boolean>(true)
// 日志相关状态
const [logFiles, setLogFiles] = useState<Array<{ name: string; size: number; mtime: Date }>>([])
@@ -219,6 +221,8 @@ function SettingsPage() {
const savedAiCustomSystemPrompt = await configService.getAiCustomSystemPrompt()
const savedAiEnableThinking = await configService.getAiEnableThinking()
const savedAiMessageLimit = await configService.getAiMessageLimit()
const savedMcpEnabled = await configService.getMcpEnabled()
const savedMcpExposeMediaPaths = await configService.getMcpExposeMediaPaths()
setAiProviderState(savedAiProvider)
setAiApiKeyState(savedAiApiKey)
@@ -229,6 +233,8 @@ function SettingsPage() {
setAiCustomSystemPromptState(savedAiCustomSystemPrompt)
setAiEnableThinkingState(savedAiEnableThinking)
setAiMessageLimitState(savedAiMessageLimit)
setMcpEnabledState(savedMcpEnabled)
setMcpExposeMediaPathsState(savedMcpExposeMediaPaths)
// 加载关闭行为配置
const savedCloseToTray = await configService.getCloseToTray()
@@ -262,6 +268,8 @@ function SettingsPage() {
aiCustomSystemPrompt: savedAiCustomSystemPrompt,
aiEnableThinking: savedAiEnableThinking,
aiMessageLimit: savedAiMessageLimit,
mcpEnabled: savedMcpEnabled,
mcpExposeMediaPaths: savedMcpExposeMediaPaths,
closeToTray: savedCloseToTray
})
@@ -310,6 +318,8 @@ function SettingsPage() {
aiCustomSystemPrompt,
aiEnableThinking,
aiMessageLimit,
mcpEnabled,
mcpExposeMediaPaths,
closeToTray
}
@@ -323,6 +333,7 @@ function SettingsPage() {
quoteStyle, exportDefaultDateRange, exportDefaultAvatars,
aiProvider, aiApiKey, aiModel, aiDefaultTimeRange, aiSummaryDetail,
aiSystemPromptPreset, aiCustomSystemPrompt, aiEnableThinking, aiMessageLimit,
mcpEnabled, mcpExposeMediaPaths,
closeToTray, initialConfig
])
@@ -848,6 +859,8 @@ function SettingsPage() {
await configService.setAiCustomSystemPrompt(aiCustomSystemPrompt)
await configService.setAiEnableThinking(aiEnableThinking)
await configService.setAiMessageLimit(aiMessageLimit)
await configService.setMcpEnabled(mcpEnabled)
await configService.setMcpExposeMediaPaths(mcpExposeMediaPaths)
// 保存关闭行为配置
await configService.setCloseToTray(closeToTray)
@@ -887,6 +900,8 @@ function SettingsPage() {
aiCustomSystemPrompt,
aiEnableThinking,
aiMessageLimit,
mcpEnabled,
mcpExposeMediaPaths,
closeToTray
})
setHasUnsavedChanges(false)
@@ -2787,6 +2802,10 @@ function SettingsPage() {
setEnableThinking={setAiEnableThinkingState}
messageLimit={aiMessageLimit}
setMessageLimit={setAiMessageLimitState}
mcpEnabled={mcpEnabled}
setMcpEnabled={setMcpEnabledState}
mcpExposeMediaPaths={mcpExposeMediaPaths}
setMcpExposeMediaPaths={setMcpExposeMediaPathsState}
showMessage={showMessage}
/>
)}
+22
View File
@@ -28,6 +28,8 @@ export const CONFIG_KEYS = {
HTTP_API_ENABLED: 'httpApiEnabled',
HTTP_API_PORT: 'httpApiPort',
HTTP_API_TOKEN: 'httpApiToken',
MCP_ENABLED: 'mcpEnabled',
MCP_EXPOSE_MEDIA_PATHS: 'mcpExposeMediaPaths',
AUTH_ENABLED: 'authEnabled',
AUTH_CREDENTIAL_ID: 'authCredentialId',
AUTH_PASSWORD_HASH: 'authPasswordHash',
@@ -509,6 +511,26 @@ export async function setAiMessageLimit(limit: number): Promise<void> {
await config.set('aiMessageLimit', limit)
}
// --- MCP 配置 ---
export async function getMcpEnabled(): Promise<boolean> {
const value = await config.get(CONFIG_KEYS.MCP_ENABLED)
return value !== undefined ? (value as boolean) : false
}
export async function setMcpEnabled(enabled: boolean): Promise<void> {
await config.set(CONFIG_KEYS.MCP_ENABLED, enabled)
}
export async function getMcpExposeMediaPaths(): Promise<boolean> {
const value = await config.get(CONFIG_KEYS.MCP_EXPOSE_MEDIA_PATHS)
return value !== undefined ? (value as boolean) : true
}
export async function setMcpExposeMediaPaths(enabled: boolean): Promise<void> {
await config.set(CONFIG_KEYS.MCP_EXPOSE_MEDIA_PATHS, enabled)
}
// --- AI 配置预设 ---
export interface AiConfigPreset {