welsonjs/WelsonJS.Augmented/WelsonJS.Launcher/JsonRpc2Dispatcher.cs
Namhyeon, Go 6b3d83fbcd Add JSON-RPC2 stdio & HTTP endpoint support
Introduce JSON-RPC 2.0 handling and a minimal stdio framing server. Adds ApiEndpoints/JsonRpc2 and JsonRpc2Dispatcher to parse and dispatch JSON-RPC requests, and StdioServer to handle Content-Length framed stdio messages. Adds McpToolsList.json (tools list resource) and wires JsonRpc2 into ResourceServer.

Program.cs: add --stdio-jsonrpc2 mode to run the stdio server, and integrate dispatcher usage (with timeout and TODO placeholders for tools/call). ResourceServer: register JsonRpc2 endpoint, change fallback handling to 404 via ServeResource(), and make several resource helper methods static/public for reuse. Update csproj to include new source files and embed the McpToolsList.json resource.

Contains basic implementation and scaffolding; tool-call handling is left as TODO.
2026-02-05 17:44:39 +09:00

80 lines
2.4 KiB
C#

using log4net;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace WelsonJS.Launcher
{
public sealed class JsonRpc2Request
{
public string Version;
public string Method;
}
public sealed class JsonRpc2Exception : Exception
{
public JsonRpc2Exception(string message) : base(message) { }
public JsonRpc2Exception(string message, Exception inner) : base(message, inner) { }
}
public sealed class JsonRpc2Dispatcher
{
private readonly ILog _logger;
public JsonRpc2Dispatcher(ILog logger)
{
_logger = logger;
}
public async Task<string> HandleAsync(
string requestBody,
Func<string, JsSerializer, CancellationToken, Task<string>> dispatchMethodAsync,
CancellationToken ct)
{
if (string.IsNullOrEmpty(requestBody))
throw new JsonRpc2Exception("Empty request body");
if (dispatchMethodAsync == null)
throw new ArgumentNullException("dispatchMethodAsync");
using (var ser = new JsSerializer())
{
int id = ser.Load(requestBody);
try
{
string version = ser.ExtractFrom(id, "jsonrpc");
if (!string.Equals(version, "2.0", StringComparison.Ordinal))
throw new JsonRpc2Exception("Unsupported jsonrpc version: " + version);
string method = ser.ExtractFrom(id, "method");
if (string.IsNullOrEmpty(method))
throw new JsonRpc2Exception("Missing method");
var req = new JsonRpc2Request
{
Version = version,
Method = method
};
return await dispatchMethodAsync(req.Method, ser, ct);
}
catch (JsonRpc2Exception)
{
throw;
}
catch (Exception ex)
{
if (_logger != null)
_logger.Error("[JsonRpc2] Parse error", ex);
throw new JsonRpc2Exception("Parse error", ex);
}
finally
{
ser.Unload(id);
}
}
}
}
}