forked from admin/VolcanicAgenticCore
Streamable HTTP/SSE servers from the workspace's .volcanic/mcp/servers.json. Headers are sealed with AES-GCM; the chat and the visible fields are the associated data, so only /mcp_add|remove|tools change servers. Tools <server>__<tool> go live in the session. An unreachable server is skipped and reported in the system prompt. Keys are redacted from tool results, and Telegram deletes messages that carry one.
38 lines
1.8 KiB
C#
38 lines
1.8 KiB
C#
namespace Volcanic.AgenticCore.Extensions.Mcp.Remote;
|
|
|
|
/// <summary>
|
|
/// Remote MCP servers per chat (<see cref="RemoteMcpExtension"/>). Process-wide; the servers themselves are per chat.
|
|
/// Without <see cref="Secret"/> the commands only explain how to turn the feature on.
|
|
/// </summary>
|
|
public sealed record RemoteMcpOptions
|
|
{
|
|
/// <summary>
|
|
/// Derives the key that seals each chat's server headers. Must be a host secret the agent's processes never see (the
|
|
/// Telegram host uses <c>MCP_ENCRYPTION_SECRET</c>, else the bot token). Changing it makes every stored server unreadable.
|
|
/// </summary>
|
|
public string? Secret { get; init; }
|
|
|
|
/// <summary>Handshake plus <c>tools/list</c>, per server. A server that misses it starts the session without its tools.</summary>
|
|
public TimeSpan ConnectTimeout { get; init; } = TimeSpan.FromSeconds(15);
|
|
|
|
/// <summary>One <c>tools/call</c>.</summary>
|
|
public TimeSpan CallTimeout { get; init; } = TimeSpan.FromSeconds(120);
|
|
|
|
/// <summary>First retry delay for a server that failed to connect; doubles per failure up to <see cref="MaxRetryDelay"/>.</summary>
|
|
public TimeSpan RetryDelay { get; init; } = TimeSpan.FromSeconds(60);
|
|
|
|
public TimeSpan MaxRetryDelay { get; init; } = TimeSpan.FromMinutes(15);
|
|
|
|
/// <summary>How long <c>/mcp_add</c> waits for the key when it asks for one.</summary>
|
|
public TimeSpan KeyPromptTimeout { get; init; } = TimeSpan.FromMinutes(5);
|
|
|
|
/// <summary>Tests pass a handler over an in-memory server; null uses one shared socket handler.</summary>
|
|
public Func<HttpMessageHandler>? HttpHandlerFactory { get; init; }
|
|
|
|
public TimeProvider? Time { get; init; }
|
|
|
|
public bool IsConfigured => !string.IsNullOrWhiteSpace(Secret);
|
|
|
|
public override string ToString() => $"RemoteMcpOptions {{ Configured = {IsConfigured}, ConnectTimeout = {ConnectTimeout} }}";
|
|
}
|