feat: implement MCP UIs

This commit is contained in:
Li Xin
2025-04-24 15:41:33 +08:00
parent d9ffb19950
commit 10b1d63834
32 changed files with 1419 additions and 321 deletions

View File

@@ -1,5 +1,10 @@
// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
// SPDX-License-Identifier: MIT
import { create } from "zustand";
import type { MCPServerMetadata } from "../mcp";
const SETTINGS_KEY = "deerflow.settings";
const DEFAULT_SETTINGS: SettingsState = {
@@ -7,6 +12,34 @@ const DEFAULT_SETTINGS: SettingsState = {
maxPlanIterations: 1,
maxStepNum: 3,
},
mcp: {
servers: [
{
enabled: true,
name: "Zapier",
transport: "sse",
url: "https://actions.zapier.com/mcp/sk-ak-OnJ4kVKzxcLjpvpLChkT7RCYuh/sse",
env: { API_KEY: "123" },
createdAt: new Date("2025-04-20").valueOf(),
updatedAt: new Date("2025-04-20").valueOf(),
tools: [
{
name: "youtube_get_report",
description:
"Creates a report on specified data from your owned and managed channels.",
},
{
name: "edit_actions",
description: "Edit your existing MCP provider actions",
},
{
name: "add_actions",
description: "Add new actions to your MCP provider",
},
],
},
],
},
};
export type SettingsState = {
@@ -14,6 +47,9 @@ export type SettingsState = {
maxPlanIterations: number;
maxStepNum: number;
};
mcp: {
servers: MCPServerMetadata[];
};
};
export const useSettingsStore = create<SettingsState>(() => ({

View File

@@ -4,13 +4,13 @@
import { nanoid } from "nanoid";
import { create } from "zustand";
import { chatStream } from "../api";
import { generatePodcast } from "../api/podcast";
import { chatStream, generatePodcast } from "../api";
import type { Message } from "../messages";
import { mergeMessage } from "../messages";
import { parseJSON } from "../utils";
import { useSettingsStore } from "./settings-store";
import type { MCPServerMetadata, SimpleMCPServerMetadata } from "../mcp";
const THREAD_ID = nanoid();
@@ -57,7 +57,52 @@ export async function sendMessage(
setResponding(true);
try {
const generalSettings = useSettingsStore.getState().general;
const settings = useSettingsStore.getState();
const generalSettings = settings.general;
const mcpServers = settings.mcp.servers.filter((server) => server.enabled);
let mcpSettings:
| {
servers: Record<
string,
MCPServerMetadata & {
enabled_tools: string[];
add_to_agents: string[];
}
>;
}
| undefined = undefined;
if (mcpServers.length > 0) {
mcpSettings = {
servers: mcpServers.reduce((acc, cur) => {
const { transport, env } = cur;
let server: SimpleMCPServerMetadata;
if (transport === "stdio") {
server = {
name: cur.name,
transport,
env,
command: cur.command,
args: cur.args,
};
} else {
server = {
name: cur.name,
transport,
env,
url: cur.url,
};
}
return {
...acc,
[cur.name]: {
...server,
enabled_tools: cur.tools.map((tool) => tool.name),
add_to_agents: ["researcher"],
},
};
}, {}),
};
}
const stream = chatStream(
content,
{
@@ -65,6 +110,7 @@ export async function sendMessage(
max_plan_iterations: generalSettings.maxPlanIterations,
max_step_num: generalSettings.maxStepNum,
interrupt_feedback: interruptFeedback,
mcp_settings: mcpSettings,
},
options,
);