Files
ClawdDotNet/src/ClawdDotNet.Core/Tools/ToolRegistry.cs
T
RichardandClaude Opus 5.5 caf4323012 MCP-Client fuer HTTP-Server: externe Werkzeuge durch dieselben Pruefstellen (#197)
- Core/Mcp/McpClient: Streamable HTTP (MCP 2025-06-18) - initialize, tools/list
  with paging, tools/call; answers as JSON or event stream; session kept and
  opened again when the server forgets it; answers capped at 4 MB.
- McpServerTool: one server is one tool (mcp_<id>); its remote tools are the
  operations, so rights, preflight, staging, lead approvals, votes, audit and
  budget apply. On approval by default unless the human trusts an operation;
  reads foreign content; the server's descriptions are cut short and marked.
- McpConnections: registers, refreshes every 15 minutes, follows changes.
- InstanceConfig.mcpServers with protected headers; /api/mcp-servers;
  settings card "External MCP servers"; tool catalog includes the servers.
- stdio servers are not part of this (sandbox runner, separate step).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 18:15:44 +02:00

61 lines
1.7 KiB
C#

using ClawdDotNet.Core.Config;
namespace ClawdDotNet.Core.Tools;
public sealed class ToolRegistry
{
private readonly Dictionary<string, IAgentTool> _tools = new();
/// <summary>
/// #689: Tools every agent has, without being granted them. Escalation is one: a case
/// nobody can raise is a case nobody solves — being able to say "I cannot get on" is not a
/// permission, it is part of working in an organisation.
/// </summary>
public static readonly IReadOnlySet<string> ImplicitTools =
new HashSet<string>(StringComparer.OrdinalIgnoreCase) { Cases.CaseDesk.ToolName };
private readonly Lock _lock = new();
public void Register(IAgentTool tool)
{
lock (_lock)
_tools[tool.Name] = tool;
}
/// <summary>#197: Takes a tool out again — an MCP server the human removed.</summary>
public bool Unregister(string name)
{
lock (_lock)
return _tools.Remove(name);
}
public IAgentTool? Get(string name)
{
lock (_lock)
return _tools.GetValueOrDefault(name);
}
public IReadOnlyList<IAgentTool> GetForAgent(AgentConfig agent)
{
lock (_lock)
return _tools.Values
.Where(t => agent.Tools.ContainsKey(t.Name) || ImplicitTools.Contains(t.Name))
.ToList();
}
public IReadOnlyList<IAgentTool> GetAll()
{
lock (_lock)
return _tools.Values.ToList();
}
public IReadOnlyList<(IAgentTool Tool, IToolJobProvider Provider)> GetJobProviders()
{
lock (_lock)
return _tools.Values
.OfType<IToolJobProvider>()
.Select(p => ((IAgentTool)p, p))
.ToList();
}
}