mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Add per-agent MCP toolset configuration to agent setup (#279)
This commit is contained in:
@@ -44,7 +44,7 @@ const overrides = new Map([
|
||||
["src/shared/api/tauri.ts", 1100], // remote agent provider API bindings + canvas API functions
|
||||
["src-tauri/src/lib.rs", 550], // sprout-media:// proxy now forwards Range headers + propagates Content-Range/Accept-Ranges for video seeking
|
||||
["src-tauri/src/commands/media.rs", 720], // ffmpeg video transcode + poster frame extraction + run_ffmpeg_with_timeout (find_ffmpeg, is_video_file, transcode_to_mp4, extract_poster_frame, transcode_and_extract_poster) + spawn_blocking wrappers + tests
|
||||
["src-tauri/src/commands/agents.rs", 849], // remote agent lifecycle routing (local + provider branches) + scope enforcement; rustfmt adds line breaks around long tuple/closure blocks
|
||||
["src-tauri/src/commands/agents.rs", 860], // remote agent lifecycle routing (local + provider branches) + scope enforcement + mcp_toolsets field; rustfmt adds line breaks around long tuple/closure blocks
|
||||
["src-tauri/src/managed_agents/runtime.rs", 650], // KNOWN_AGENT_BINARIES const + process_belongs_to_us FFI (macOS proc_name + Linux /proc/comm) + terminate_process + start/stop/sync lifecycle
|
||||
["src-tauri/src/managed_agents/backend.rs", 530], // provider IPC, validation, discovery, binary resolution + tests
|
||||
["src/features/agents/hooks.ts", 520], // agent query/mutation surface now includes built-in persona library activation
|
||||
@@ -54,7 +54,7 @@ const overrides = new Map([
|
||||
["src/features/agents/ui/useTeamActions.ts", 510], // team CRUD + export + import + import-update orchestration with query invalidation
|
||||
["src/features/agents/ui/CreateAgentDialog.tsx", 685], // provider selector + config form + schema-typed config coercion + required field validation + locked scopes
|
||||
["src/features/channels/ui/AddChannelBotDialog.tsx", 640], // provider mode: Run on selector, trust warning, probe effect, single-agent enforcement, provider warnings display
|
||||
["src/shared/api/types.ts", 530], // persona provider/model fields + forum types + workflow type re-exports + ephemeral channel TTL fields
|
||||
["src/shared/api/types.ts", 535], // persona provider/model fields + forum types + workflow type re-exports + ephemeral channel TTL fields + mcpToolsets
|
||||
]);
|
||||
|
||||
async function walkFiles(directory) {
|
||||
|
||||
@@ -130,6 +130,13 @@ pub fn update_managed_agent(
|
||||
if let Some(prompt_update) = input.system_prompt {
|
||||
record.system_prompt = prompt_update;
|
||||
}
|
||||
if let Some(toolsets_update) = input.mcp_toolsets {
|
||||
record.mcp_toolsets = toolsets_update
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|v| !v.is_empty())
|
||||
.map(str::to_string);
|
||||
}
|
||||
record.updated_at = now_iso();
|
||||
|
||||
save_managed_agents(&app, &records)?;
|
||||
|
||||
@@ -385,6 +385,12 @@ pub async fn create_managed_agent(
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(str::to_string),
|
||||
mcp_toolsets: input
|
||||
.mcp_toolsets
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(str::to_string),
|
||||
// Provider agents don't auto-start with the desktop — they're
|
||||
// managed externally. Force false to avoid persisting a flag the
|
||||
// app will never honor.
|
||||
|
||||
@@ -407,6 +407,7 @@ pub fn build_managed_agent_summary(
|
||||
parallelism: record.parallelism,
|
||||
system_prompt: record.system_prompt.clone(),
|
||||
model: record.model.clone(),
|
||||
mcp_toolsets: record.mcp_toolsets.clone(),
|
||||
has_api_token: record.api_token.is_some(),
|
||||
backend: record.backend.clone(),
|
||||
backend_agent_id: record.backend_agent_id.clone(),
|
||||
@@ -526,6 +527,11 @@ pub fn start_managed_agent_process(
|
||||
} else {
|
||||
command.env_remove("SPROUT_ACP_MODEL");
|
||||
}
|
||||
if let Some(toolsets) = &record.mcp_toolsets {
|
||||
command.env("SPROUT_TOOLSETS", toolsets);
|
||||
} else {
|
||||
command.env_remove("SPROUT_TOOLSETS");
|
||||
}
|
||||
command.env_remove("SPROUT_ACP_PRIVATE_KEY");
|
||||
command.env_remove("SPROUT_ACP_API_TOKEN");
|
||||
|
||||
|
||||
@@ -77,6 +77,10 @@ pub struct ManagedAgentRecord {
|
||||
/// creation by matching this ID against the fresh session/new response.
|
||||
#[serde(default)]
|
||||
pub model: Option<String>,
|
||||
/// Comma-separated toolset string forwarded as SPROUT_TOOLSETS to the MCP subprocess.
|
||||
/// When None, the MCP server uses its own default ("default" toolset).
|
||||
#[serde(default)]
|
||||
pub mcp_toolsets: Option<String>,
|
||||
#[serde(default = "default_start_on_app_launch")]
|
||||
pub start_on_app_launch: bool,
|
||||
#[serde(default)]
|
||||
@@ -117,6 +121,7 @@ pub struct ManagedAgentSummary {
|
||||
pub parallelism: u32,
|
||||
pub system_prompt: Option<String>,
|
||||
pub model: Option<String>,
|
||||
pub mcp_toolsets: Option<String>,
|
||||
pub has_api_token: bool,
|
||||
pub backend: BackendKind,
|
||||
pub backend_agent_id: Option<String>,
|
||||
@@ -151,6 +156,7 @@ pub struct CreateManagedAgentRequest {
|
||||
pub system_prompt: Option<String>,
|
||||
pub avatar_url: Option<String>,
|
||||
pub model: Option<String>,
|
||||
pub mcp_toolsets: Option<String>,
|
||||
#[serde(default)]
|
||||
pub mint_token: bool,
|
||||
#[serde(default)]
|
||||
@@ -271,6 +277,8 @@ pub struct UpdateManagedAgentRequest {
|
||||
pub model: Option<Option<String>>,
|
||||
#[serde(default)]
|
||||
pub system_prompt: Option<Option<String>>,
|
||||
#[serde(default)]
|
||||
pub mcp_toolsets: Option<Option<String>>,
|
||||
}
|
||||
|
||||
/// Response from `get_agent_models` — normalized model info for the frontend.
|
||||
|
||||
@@ -53,6 +53,7 @@ export function CreateAgentDialog({
|
||||
const [agentCommand, setAgentCommand] = React.useState("goose");
|
||||
const [agentArgs, setAgentArgs] = React.useState("acp");
|
||||
const [mcpCommand, setMcpCommand] = React.useState("sprout-mcp-server");
|
||||
const [mcpToolsets, setMcpToolsets] = React.useState("");
|
||||
const prereqsQuery = useManagedAgentPrereqsQuery(acpCommand, mcpCommand);
|
||||
const [name, setName] = React.useState("");
|
||||
const [relayUrl, setRelayUrl] = React.useState("");
|
||||
@@ -213,6 +214,7 @@ export function CreateAgentDialog({
|
||||
setAgentCommand("goose");
|
||||
setAgentArgs("acp");
|
||||
setMcpCommand("sprout-mcp-server");
|
||||
setMcpToolsets("");
|
||||
setTurnTimeoutSeconds("320");
|
||||
setParallelism("3");
|
||||
setSystemPrompt("");
|
||||
@@ -355,6 +357,7 @@ export function CreateAgentDialog({
|
||||
.map((value) => value.trim())
|
||||
.filter((value) => value.length > 0),
|
||||
mcpCommand: mcpCommand.trim() || undefined,
|
||||
mcpToolsets: mcpToolsets.trim() || undefined,
|
||||
turnTimeoutSeconds:
|
||||
Number.parseInt(turnTimeoutSeconds, 10) > 0
|
||||
? Number.parseInt(turnTimeoutSeconds, 10)
|
||||
@@ -530,11 +533,13 @@ export function CreateAgentDialog({
|
||||
agentArgs={agentArgs}
|
||||
agentCommand={agentCommand}
|
||||
mcpCommand={mcpCommand}
|
||||
mcpToolsets={mcpToolsets}
|
||||
onParallelismChange={setParallelism}
|
||||
onAcpCommandChange={setAcpCommand}
|
||||
onAgentArgsChange={setAgentArgs}
|
||||
onAgentCommandChange={setAgentCommand}
|
||||
onMcpCommandChange={setMcpCommand}
|
||||
onMcpToolsetsChange={setMcpToolsets}
|
||||
onRelayUrlChange={setRelayUrl}
|
||||
onSystemPromptChange={setSystemPrompt}
|
||||
onTurnTimeoutChange={setTurnTimeoutSeconds}
|
||||
|
||||
@@ -100,6 +100,7 @@ export function CreateAgentRuntimeFields({
|
||||
agentArgs,
|
||||
agentCommand,
|
||||
mcpCommand,
|
||||
mcpToolsets,
|
||||
parallelism,
|
||||
relayUrl,
|
||||
selectedProviderId,
|
||||
@@ -109,6 +110,7 @@ export function CreateAgentRuntimeFields({
|
||||
onAgentArgsChange,
|
||||
onAgentCommandChange,
|
||||
onMcpCommandChange,
|
||||
onMcpToolsetsChange,
|
||||
onParallelismChange,
|
||||
onRelayUrlChange,
|
||||
onSystemPromptChange,
|
||||
@@ -118,6 +120,7 @@ export function CreateAgentRuntimeFields({
|
||||
agentArgs: string;
|
||||
agentCommand: string;
|
||||
mcpCommand: string;
|
||||
mcpToolsets: string;
|
||||
parallelism: string;
|
||||
relayUrl: string;
|
||||
selectedProviderId: string;
|
||||
@@ -127,6 +130,7 @@ export function CreateAgentRuntimeFields({
|
||||
onAgentArgsChange: (value: string) => void;
|
||||
onAgentCommandChange: (value: string) => void;
|
||||
onMcpCommandChange: (value: string) => void;
|
||||
onMcpToolsetsChange: (value: string) => void;
|
||||
onParallelismChange: (value: string) => void;
|
||||
onRelayUrlChange: (value: string) => void;
|
||||
onSystemPromptChange: (value: string) => void;
|
||||
@@ -280,6 +284,23 @@ export function CreateAgentRuntimeFields({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-sm font-medium" htmlFor="agent-mcp-toolsets">
|
||||
MCP toolsets
|
||||
</label>
|
||||
<Input
|
||||
id="agent-mcp-toolsets"
|
||||
onChange={(event) => onMcpToolsetsChange(event.target.value)}
|
||||
placeholder="default"
|
||||
value={mcpToolsets}
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Comma-separated list of toolsets to expose via SPROUT_TOOLSETS.
|
||||
Available: default, channel_admin, dms, canvas, workflow_admin,
|
||||
identity, forums, social. Leave blank for the default toolset only.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-sm font-medium" htmlFor="agent-system-prompt">
|
||||
System prompt override
|
||||
|
||||
@@ -240,6 +240,7 @@ export type RawManagedAgent = {
|
||||
parallelism: number;
|
||||
system_prompt: string | null;
|
||||
model: string | null;
|
||||
mcp_toolsets: string | null;
|
||||
has_api_token: boolean;
|
||||
status: ManagedAgent["status"];
|
||||
pid: number | null;
|
||||
@@ -831,6 +832,7 @@ export function fromRawManagedAgent(agent: RawManagedAgent): ManagedAgent {
|
||||
parallelism: agent.parallelism,
|
||||
systemPrompt: agent.system_prompt,
|
||||
model: agent.model,
|
||||
mcpToolsets: agent.mcp_toolsets,
|
||||
hasApiToken: agent.has_api_token,
|
||||
status: agent.status,
|
||||
pid: agent.pid,
|
||||
@@ -927,6 +929,7 @@ export async function createManagedAgent(input: CreateManagedAgentInput) {
|
||||
agentCommand: input.agentCommand,
|
||||
agentArgs: input.agentArgs,
|
||||
mcpCommand: input.mcpCommand,
|
||||
mcpToolsets: input.mcpToolsets,
|
||||
turnTimeoutSeconds: input.turnTimeoutSeconds,
|
||||
idleTimeoutSeconds: input.idleTimeoutSeconds,
|
||||
maxTurnDurationSeconds: input.maxTurnDurationSeconds,
|
||||
|
||||
@@ -294,6 +294,7 @@ export type ManagedAgent = {
|
||||
parallelism: number;
|
||||
systemPrompt: string | null;
|
||||
model: string | null;
|
||||
mcpToolsets: string | null;
|
||||
hasApiToken: boolean;
|
||||
status: "running" | "stopped" | "deployed" | "not_deployed";
|
||||
pid: number | null;
|
||||
@@ -337,6 +338,7 @@ export type CreateManagedAgentInput = {
|
||||
systemPrompt?: string;
|
||||
avatarUrl?: string;
|
||||
model?: string;
|
||||
mcpToolsets?: string;
|
||||
mintToken?: boolean;
|
||||
tokenScopes?: TokenScope[];
|
||||
tokenName?: string;
|
||||
@@ -407,6 +409,7 @@ export type UpdateManagedAgentInput = {
|
||||
name?: string;
|
||||
model?: string | null;
|
||||
systemPrompt?: string | null;
|
||||
mcpToolsets?: string | null;
|
||||
};
|
||||
export type AgentPersona = {
|
||||
id: string;
|
||||
|
||||
Reference in New Issue
Block a user