Loopback MCP host with observe/control/develop gates and a hot-reload tools DLL. Default token is local-dev only. Leave the module off unless you are driving S3 from an agent.
62 lines
1.6 KiB
C#
62 lines
1.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Newtonsoft.Json.Linq;
|
|
using S3.Mcp;
|
|
|
|
namespace S3.Modules.Mcp;
|
|
|
|
sealed class McpToolEntry
|
|
{
|
|
public string Name = "";
|
|
public string Description = "";
|
|
public JObject InputSchema = new();
|
|
public McpGate Gate;
|
|
public string Source = "host";
|
|
public Func<JObject, McpToolResult> Handler = _ => McpToolResult.Fail("no handler");
|
|
}
|
|
|
|
sealed class McpRegistry
|
|
{
|
|
readonly List<McpToolEntry> _tools = new();
|
|
|
|
public IReadOnlyList<McpToolEntry> All => _tools;
|
|
|
|
public void ClearSource(string source)
|
|
{
|
|
for (int i = _tools.Count - 1; i >= 0; i--)
|
|
if (_tools[i].Source == source)
|
|
_tools.RemoveAt(i);
|
|
}
|
|
|
|
public void Add(McpToolEntry entry)
|
|
{
|
|
for (int i = _tools.Count - 1; i >= 0; i--)
|
|
if (_tools[i].Name == entry.Name)
|
|
_tools.RemoveAt(i);
|
|
_tools.Add(entry);
|
|
}
|
|
|
|
public McpToolEntry? Find(string name)
|
|
{
|
|
for (int i = 0; i < _tools.Count; i++)
|
|
if (_tools[i].Name == name)
|
|
return _tools[i];
|
|
return null;
|
|
}
|
|
|
|
public List<McpToolEntry> Visible()
|
|
{
|
|
var s = McpModule.Settings;
|
|
var list = new List<McpToolEntry>();
|
|
for (int i = 0; i < _tools.Count; i++)
|
|
{
|
|
var t = _tools[i];
|
|
if (t.Source == "host") { list.Add(t); continue; }
|
|
if (t.Gate == McpGate.Observe && !s.observe) continue;
|
|
if (t.Gate == McpGate.Control && !s.control) continue;
|
|
if (t.Gate == McpGate.Develop && !s.develop) continue;
|
|
list.Add(t);
|
|
}
|
|
return list;
|
|
}
|
|
}
|