Voltaic 0.1.6
dotnet add package Voltaic --version 0.1.6
NuGet\Install-Package Voltaic -Version 0.1.6
<PackageReference Include="Voltaic" Version="0.1.6" />
<PackageVersion Include="Voltaic" Version="0.1.6" />
<PackageReference Include="Voltaic" />
paket add Voltaic --version 0.1.6
#r "nuget: Voltaic, 0.1.6"
#:package Voltaic@0.1.6
#addin nuget:?package=Voltaic&version=0.1.6
#tool nuget:?package=Voltaic&version=0.1.6
<div align="center"> <img src="assets/logo.png" alt="Voltaic Logo" width="192" height="192"> </div>
Voltaic
Modern, lightweight JSON-RPC 2.0 and MCP implementations for .NET 8.0
Voltaic provides client and server implementations for JSON-RPC 2.0 and the Model Context Protocol (MCP). Whether you're building microservices, AI integrations, or distributed systems—Voltaic gives you the tools to communicate clearly and reliably.
What's Inside
JSON-RPC 2.0
A complete JSON-RPC 2.0 implementation with TCP-based client and server. Perfect for building RPC-based APIs, microservices, and distributed applications.
Features:
- Full JSON-RPC 2.0 specification compliance
- TCP-based transport with LSP-style message framing (
Content-Lengthheaders) - Async/await throughout for modern .NET performance
- Support for requests, responses, notifications, and broadcasts
- Type-safe method registration and invocation
- Connection management with graceful shutdown
- Thread-safe concurrent request handling
- Event-driven architecture with connection and request/response events
- Per-client notification queue management with configurable limits
Model Context Protocol (MCP)
Client and server implementations for Anthropic's Model Context Protocol, supporting multiple transport options.
Features:
- Stdio transport: Subprocess-based MCP servers (standard MCP pattern)
- TCP transport: Network-based MCP communication with LSP-style framing
- HTTP transport: HTTP-based MCP communication with Server-Sent Events (SSE) for notifications
- WebSocket transport: Full-duplex bidirectional communication
- Implements JSON-RPC 2.0 protocol across all transports
- Process lifecycle management for subprocess servers
- Event-driven notification handling with connection lifecycle events
- Request/response event tracking with timing information
- Compatible with MCP server ecosystem
Important
Voltaic currently does not support authorization, which is listed as OPTIONAL in the spec.
Who Is This For?
Voltaic is designed for developers who need:
- Microservice Communication: Build services that talk to each other using a standard RPC protocol
- AI Tool Integration: Connect to MCP servers for AI assistant integrations (Claude, etc.)
- Custom RPC APIs: Implement your own remote procedure call interfaces
- Subprocess Orchestration: Launch and communicate with child processes using stdio transport
- Language Server Protocols: Build LSP-style applications that use Content-Length framing
- Real-time Systems: Low-latency RPC communication over TCP sockets
- Web-based Integration: HTTP and WebSocket transports for browser-compatible communication
- Flexible Transport Options: Choose the right transport for your architecture
If you're building .NET applications that need structured, bidirectional communication, Voltaic has you covered.
Getting Started
Installation
# Install the Voltaic package
dotnet add package Voltaic
Quick Start: JSON-RPC Server (TCP)
using System.Net;
using System.Text.Json;
using Voltaic;
JsonRpcServer server = new JsonRpcServer(IPAddress.Any, 8080);
// Subscribe to events
server.ClientConnected += (sender, client) =>
Console.WriteLine($"Client connected: {client.SessionId}");
server.RequestReceived += (sender, e) =>
Console.WriteLine($"Request: {e.Method} from {e.Client.SessionId}");
server.ResponseSent += (sender, e) =>
Console.WriteLine($"Response: {e.Method} took {e.Duration.TotalMilliseconds}ms");
// Register custom methods
server.RegisterMethod("greet", (JsonElement? args) =>
{
string? name = args?.TryGetProperty("name", out JsonElement nameEl) == true
? nameEl.GetString()
: "World";
return $"Hello, {name}!";
});
// Start the server
await server.StartAsync();
Console.WriteLine("Server running on port 8080");
// Keep it running
await Task.Delay(Timeout.Infinite, server.TokenSource.Token);
Quick Start: JSON-RPC Client (TCP)
using Voltaic;
JsonRpcClient client = new JsonRpcClient();
// Subscribe to notification events from server
client.NotificationReceived += (sender, request) =>
Console.WriteLine($"Server notification: {request.Method}");
await client.ConnectAsync("localhost", 8080);
// Call a method with typed response
string greeting = await client.CallAsync<string>("greet", new { name = "Developer" });
Console.WriteLine(greeting); // "Hello, Developer!"
// Send a notification (no response expected)
await client.NotifyAsync("logEvent", new { level = "info", message = "User logged in" });
Quick Start: MCP Server (stdio)
using System.Text.Json;
using Voltaic;
McpServer server = new McpServer();
// Register MCP methods
server.RegisterMethod("tools/list", (JsonElement? args) =>
{
return new
{
tools = new[]
{
new { name = "calculator", description = "Performs calculations" }
}
};
});
// Run the server (reads from stdin, writes to stdout)
await server.RunAsync();
Quick Start: MCP Client (stdio)
using Voltaic;
McpClient client = new McpClient();
// Launch an MCP server as a subprocess
await client.LaunchServerAsync("dotnet", new[] { "run", "--project", "MyMcpServer" });
// Call methods on the server
JsonRpcResponse response = await client.CallAsync("tools/list");
Console.WriteLine(response.Result);
Quick Start: MCP Server (TCP)
using System.Net;
using System.Text.Json;
using Voltaic;
McpTcpServer server = new McpTcpServer(IPAddress.Any, 8080);
// Subscribe to events
server.ClientConnected += (sender, client) =>
Console.WriteLine($"Client connected: {client.SessionId}");
server.ClientDisconnected += (sender, client) =>
Console.WriteLine($"Client disconnected: {client.SessionId}");
// Register MCP methods
server.RegisterMethod("tools/list", (JsonElement? args) =>
{
return new
{
tools = new[]
{
new { name = "calculator", description = "Performs calculations" }
}
};
});
// Start the server
await server.StartAsync();
Console.WriteLine("MCP server running on port 8080");
await Task.Delay(Timeout.Infinite, server.TokenSource.Token);
Quick Start: MCP Client (TCP)
using Voltaic;
McpTcpClient client = new McpTcpClient();
// Subscribe to server notifications
client.NotificationReceived += (sender, request) =>
Console.WriteLine($"Server notification: {request.Method}");
// Connect to the TCP server
await client.ConnectAsync("localhost", 8080);
// Call methods on the server
object? tools = await client.CallAsync<object>("tools/list");
Console.WriteLine(tools);
Quick Start: MCP Server (HTTP)
using System.Text.Json;
using Voltaic;
McpHttpServer server = new McpHttpServer("localhost", 8080);
// Subscribe to events
server.ClientConnected += (sender, client) =>
Console.WriteLine($"Session started: {client.SessionId}");
server.RequestReceived += (sender, e) =>
Console.WriteLine($"Request: {e.Method} from session {e.Client.SessionId}");
// Register MCP methods
server.RegisterMethod("tools/list", (JsonElement? args) =>
{
return new
{
tools = new[]
{
new { name = "calculator", description = "Performs calculations" }
}
};
});
// Start the server
await server.StartAsync();
Console.WriteLine("MCP HTTP server running on http://localhost:8080");
await Task.Delay(Timeout.Infinite, server.TokenSource.Token);
Quick Start: MCP Client (HTTP)
using Voltaic;
McpHttpClient client = new McpHttpClient();
// Connect to the HTTP server
await client.ConnectAsync("http://localhost:8080");
// Start SSE connection for server notifications
await client.StartSseAsync();
// Call methods on the server
object? result = await client.CallAsync<object>("tools/list");
Console.WriteLine(result);
Quick Start: MCP Server (WebSocket)
using System.Text.Json;
using Voltaic;
McpWebsocketsServer server = new McpWebsocketsServer("localhost", 8080);
// Subscribe to events
server.ClientConnected += (sender, client) =>
Console.WriteLine($"WebSocket client connected: {client.SessionId}");
server.ResponseSent += (sender, e) =>
Console.WriteLine($"Sent response for {e.Method} in {e.Duration.TotalMilliseconds}ms");
// Register MCP methods
server.RegisterMethod("tools/list", (JsonElement? args) =>
{
return new
{
tools = new[]
{
new { name = "calculator", description = "Performs calculations" }
}
};
});
// Start the server
await server.StartAsync();
Console.WriteLine("MCP WebSocket server running on ws://localhost:8080");
await Task.Delay(Timeout.Infinite, server.TokenSource.Token);
Quick Start: MCP Client (WebSocket)
using Voltaic;
McpWebsocketsClient client = new McpWebsocketsClient();
// Subscribe to server notifications
client.NotificationReceived += (sender, request) =>
Console.WriteLine($"Server notification: {request.Method}");
// Connect to the WebSocket server
await client.ConnectAsync("ws://localhost:8080/mcp");
// Call methods on the server
object? result = await client.CallAsync<object>("tools/list");
Console.WriteLine(result);
// Send a notification
await client.NotifyAsync("log", new { message = "Hello from WebSocket client" });
When NOT to Use This
Voltaic might not be the right fit if you need:
- gRPC Features: If you need streaming, advanced load balancing, or language-agnostic service definitions, use gRPC
- REST Conventions: If you need resource-oriented APIs with standard HTTP verbs, use web APIs or a REST microservice
- High-level Abstractions: Voltaic is a protocol library, not a framework — you'll write your own business logic
Documentation
All classes and methods are available in the Voltaic namespace.
JSON-RPC Server and Client
Server API (JsonRpcServer):
Constructor:
JsonRpcServer(IPAddress ip, int port, bool includeDefaultMethods = true)- Create a server listening on the specified IP address and port
Methods:
void RegisterMethod(string name, Func<JsonElement?, object> handler)- Register an RPC methodTask StartAsync(CancellationToken token = default)- Start accepting connectionsTask BroadcastNotificationAsync(string method, object? parameters, CancellationToken token = default)- Send notifications to all clientsList<string> GetConnectedClients()- Get list of connected client IDsbool KickClient(string clientId)- Disconnect a specific client by IDvoid Stop()- Gracefully shut down the server
Properties:
int MaxQueueSize { get; set; }- Maximum queued notifications per client (default: 100, min: 1)CancellationTokenSource? TokenSource { get; }- Cancellation token source for the serverstring DefaultContentType { get; set; }- Content-Type header for messages (default: "application/json; charset=utf-8")
Events:
event EventHandler<ClientConnection> ClientConnected- Fires when a client connectsevent EventHandler<ClientConnection> ClientDisconnected- Fires when a client disconnectsevent EventHandler<JsonRpcRequestEventArgs> RequestReceived- Fires when a request is receivedevent EventHandler<JsonRpcResponseEventArgs> ResponseSent- Fires when a response is sentevent EventHandler<string> Log- Fires when a log message is generated
Client API (JsonRpcClient):
Methods:
Task<bool> ConnectAsync(string host, int port, CancellationToken token = default)- Connect to a serverTask<T> CallAsync<T>(string method, object? parameters = null, int timeoutMs = 30000, CancellationToken token = default)- Make an RPC call and await typed responseTask<JsonRpcResponse> CallAsync(string method, object? parameters = null, int timeoutMs = 30000, CancellationToken token = default)- Make an RPC call and await responseTask NotifyAsync(string method, object? parameters = null, CancellationToken token = default)- Send a notification (no response)void Disconnect()- Close the connection
Properties:
bool IsConnected { get; }- Whether the client is currently connectedTcpClient? TcpClient { get; }- Underlying TCP clientCancellationTokenSource? TokenSource { get; }- Cancellation token sourcestring DefaultContentType { get; set; }- Content-Type header for messages
Events:
event EventHandler<JsonRpcRequest> NotificationReceived- Fires when a notification is received from the serverevent EventHandler<string> Log- Fires when a log message is generated
MCP Servers and Clients
McpServer (stdio):
Methods:
void RegisterMethod(string name, Func<JsonElement?, object> handler)- Register an MCP methodvoid RegisterTool(string name, string description, object inputSchema, Func<JsonElement?, object> handler)- Register tool with metadataTask RunAsync(CancellationToken token = default)- Run the server (blocks until stdin closes)
Events:
event EventHandler<string> Log- Fires when a log message is generated
McpClient (stdio):
Methods:
Task<bool> LaunchServerAsync(string executable, string[] args, CancellationToken token = default)- Launch subprocess serverTask<T> CallAsync<T>(string method, object? parameters = null, int timeoutMs = 30000, CancellationToken token = default)- Call server method with typed responseTask<JsonRpcResponse> CallAsync(string method, object? parameters = null, int timeoutMs = 30000, CancellationToken token = default)- Call server methodTask NotifyAsync(string method, object? parameters = null, CancellationToken token = default)- Send notificationvoid StopServer()- Stop the subprocess server
Events:
event EventHandler<JsonRpcRequest> NotificationReceived- Handle server notificationsevent EventHandler<string> Log- Fires when a log message is generated
McpTcpServer (TCP-based MCP):
Inherits from JsonRpcServer with additional MCP-specific built-in methods. All JsonRpcServer APIs apply, plus:
Additional Built-in Methods:
initialize- MCP protocol initializationtools/list- List registered toolstools/call- Invoke a tool by name
McpTcpClient (TCP-based MCP):
Methods:
- Same as
JsonRpcClient Task<bool> ConnectAsync(string host, int port, CancellationToken token = default)- Connect to TCP serverTask<T> CallAsync<T>(string method, object? parameters = null, int timeoutMs = 30000, CancellationToken token = default)- Call with typed response
McpHttpServer (HTTP-based MCP with SSE):
Constructor:
McpHttpServer(string hostname, int port, string rpcPath = "/rpc", string eventsPath = "/events", bool includeDefaultMethods = true)
Methods:
void RegisterMethod(string name, Func<JsonElement?, object> handler)- Register an RPC methodvoid RegisterTool(string name, string description, object inputSchema, Func<JsonElement?, object> handler)- Register tool with metadataTask StartAsync(CancellationToken token = default)- Start the HTTP serverbool SendNotificationToSession(string sessionId, string method, object? parameters = null)- Send notification to specific sessionvoid BroadcastNotification(string method, object? parameters = null)- Broadcast to all sessionsList<string> GetActiveSessions()- Get list of active session IDsList<string> GetConnectedClients()- Get list of connected client IDsbool KickClient(string clientId)- Disconnect a specific clientbool RemoveSession(string sessionId)- Remove a sessionvoid Stop()- Stop the server
Properties:
int SessionTimeoutSeconds { get; set; }- Session timeout (default: 300, min: 10)int MaxQueueSize { get; set; }- Max queued notifications per client (default: 100, min: 1)bool EnableCors { get; set; }- Enable CORS support (default: true)Dictionary<string, string> CorsHeaders { get; set; }- CORS headers configurationstring ProtocolVersion { get; set; }- MCP protocol version (default: "2025-03-26")string ServerName { get; set; }- Server name for MCP serverInfostring ServerVersion { get; set; }- Server version for MCP serverInfo
Events:
event EventHandler<ClientConnection> ClientConnected- Fires when a session is createdevent EventHandler<ClientConnection> ClientDisconnected- Fires when a session is removedevent EventHandler<JsonRpcRequestEventArgs> RequestReceived- Fires when a request is receivedevent EventHandler<JsonRpcResponseEventArgs> ResponseSent- Fires when a response is sentevent EventHandler<string> Log- Fires when a log message is generated
McpHttpClient (HTTP-based MCP):
Methods:
Task<bool> ConnectAsync(string baseUrl, CancellationToken token = default)- Connect to HTTP serverTask<bool> StartSseAsync(CancellationToken token = default)- Start Server-Sent Events for notificationsvoid StopSse()- Stop SSE connectionTask<T> CallAsync<T>(string method, object? parameters = null, int timeoutMs = 30000, CancellationToken token = default)- Call with typed responseTask<JsonRpcResponse> CallAsync(string method, object? parameters = null, int timeoutMs = 30000, CancellationToken token = default)- Call methodTask NotifyAsync(string method, object? parameters = null, CancellationToken token = default)- Send notification
Properties:
string? SessionId { get; }- Session ID assigned by serverbool IsConnected { get; }- Connection status
Events:
event EventHandler<JsonRpcRequest> NotificationReceived- Handle server notificationsevent EventHandler<string> Log- Fires when a log message is generated
McpWebsocketsServer (WebSocket-based MCP):
Constructor:
McpWebsocketsServer(string hostname, int port, string path = "/mcp", bool includeDefaultMethods = true)
Methods:
void RegisterMethod(string name, Func<JsonElement?, object> handler)- Register an RPC methodvoid RegisterTool(string name, string description, object inputSchema, Func<JsonElement?, object> handler)- Register tool with metadataTask StartAsync(CancellationToken token = default)- Start the WebSocket serverTask BroadcastNotificationAsync(string method, object? parameters = null, CancellationToken token = default)- Broadcast to all clientsList<string> GetConnectedClients()- Get list of connected client IDsbool KickClient(string clientId)- Disconnect a specific clientvoid Stop()- Stop the server
Properties:
int MaxMessageSize { get; set; }- Maximum message size in bytes (default: 1MB, min: 4096)int KeepAliveIntervalSeconds { get; set; }- WebSocket keep-alive interval (default: 30, 0 to disable)int MaxQueueSize { get; set; }- Max queued notifications per client (default: 100, min: 1)string ProtocolVersion { get; set; }- MCP protocol versionstring ServerName { get; set; }- Server name for MCP serverInfostring ServerVersion { get; set; }- Server version for MCP serverInfo
Events:
event EventHandler<ClientConnection> ClientConnected- Fires when a client connectsevent EventHandler<ClientConnection> ClientDisconnected- Fires when a client disconnectsevent EventHandler<JsonRpcRequestEventArgs> RequestReceived- Fires when a request is receivedevent EventHandler<JsonRpcResponseEventArgs> ResponseSent- Fires when a response is sentevent EventHandler<string> Log- Fires when a log message is generated
McpWebsocketsClient (WebSocket-based MCP):
Methods:
Task<bool> ConnectAsync(string url, CancellationToken token = default)- Connect to WebSocket serverTask<T> CallAsync<T>(string method, object? parameters = null, int timeoutMs = 30000, CancellationToken token = default)- Call with typed responseTask<JsonRpcResponse> CallAsync(string method, object? parameters = null, int timeoutMs = 30000, CancellationToken token = default)- Call methodTask NotifyAsync(string method, object? parameters = null, CancellationToken token = default)- Send notificationvoid Disconnect()- Close connection
Properties:
bool IsConnected { get; }- Connection statusint MaxMessageSize { get; set; }- Maximum message size
Events:
event EventHandler<JsonRpcRequest> NotificationReceived- Handle server notificationsevent EventHandler<string> Log- Fires when a log message is generated
Event Handler Examples
All server types support event handlers for monitoring connection lifecycle and request/response activity:
Monitoring Client Connections:
using System.Net;
using Voltaic;
JsonRpcServer server = new JsonRpcServer(IPAddress.Any, 8080);
server.ClientConnected += (sender, client) =>
{
Console.WriteLine($"New client: {client.SessionId}");
Console.WriteLine($"Connection type: {client.Type}");
Console.WriteLine($"Connected at: {client.LastActivity:yyyy-MM-dd HH:mm:ss}");
};
server.ClientDisconnected += (sender, client) =>
{
Console.WriteLine($"Client {client.SessionId} disconnected");
Console.WriteLine($"Queued notifications: {client.Count()}");
};
await server.StartAsync();
Tracking Requests and Responses:
using System.Net;
using Voltaic;
JsonRpcServer server = new JsonRpcServer(IPAddress.Any, 8080);
server.RequestReceived += (sender, e) =>
{
Console.WriteLine($"[{e.ReceivedUtc:HH:mm:ss.fff}] Request from {e.Client.SessionId}");
Console.WriteLine($" Method: {e.Method}");
Console.WriteLine($" Request ID: {e.RequestId}");
Console.WriteLine($" Is Notification: {e.IsNotification}");
};
server.ResponseSent += (sender, e) =>
{
string status = e.IsSuccess ? "✓" : "✗";
Console.WriteLine($"[{e.SentUtc:HH:mm:ss.fff}] {status} Response to {e.Client.SessionId}");
Console.WriteLine($" Method: {e.Method}");
Console.WriteLine($" Duration: {e.Duration.TotalMilliseconds:F2}ms");
Console.WriteLine($" Success: {e.IsSuccess}");
if (e.IsError)
{
Console.WriteLine($" Error: {e.Response.Error?.Message}");
}
};
await server.StartAsync();
Managing Client Queues:
using System.Net;
using Voltaic;
JsonRpcServer server = new JsonRpcServer(IPAddress.Any, 8080);
// Configure queue size
server.MaxQueueSize = 50; // Max 50 notifications per client
server.ClientConnected += (sender, client) =>
{
// Per-client queue configuration
client.MaxQueueSize = 100; // Override for this specific client
Console.WriteLine($"Client {client.SessionId} queue size: {client.MaxQueueSize}");
};
// Monitor queue activity
server.ResponseSent += (sender, e) =>
{
int queuedCount = e.Client.Count();
if (queuedCount > 40)
{
Console.WriteLine($"WARNING: Client {e.Client.SessionId} queue is {queuedCount}/50");
}
};
await server.StartAsync();
Building Request Metrics:
using System.Collections.Concurrent;
using System.Net;
using Voltaic;
JsonRpcServer server = new JsonRpcServer(IPAddress.Any, 8080);
ConcurrentDictionary<string, int> requestCounts = new();
ConcurrentDictionary<string, List<double>> responseTimes = new();
server.RequestReceived += (sender, e) =>
{
requestCounts.AddOrUpdate(e.Method, 1, (key, count) => count + 1);
};
server.ResponseSent += (sender, e) =>
{
double ms = e.Duration.TotalMilliseconds;
responseTimes.AddOrUpdate(
e.Method,
new List<double> { ms },
(key, list) => { list.Add(ms); return list; }
);
};
// Print stats every 10 seconds
Timer statsTimer = new Timer(_ =>
{
Console.WriteLine("\n=== Request Statistics ===");
foreach (var kvp in requestCounts.OrderByDescending(x => x.Value))
{
var times = responseTimes.GetValueOrDefault(kvp.Key, new List<double>());
double avgMs = times.Count > 0 ? times.Average() : 0;
Console.WriteLine($"{kvp.Key}: {kvp.Value} requests, avg {avgMs:F2}ms");
}
}, null, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10));
await server.StartAsync();
Handling Client Notifications:
using Voltaic;
JsonRpcClient client = new JsonRpcClient();
client.NotificationReceived += (sender, request) =>
{
Console.WriteLine($"Server notification: {request.Method}");
// Handle specific notification types
switch (request.Method)
{
case "server/shutdown":
Console.WriteLine("Server is shutting down!");
break;
case "broadcast":
var message = request.Params?.ToString();
Console.WriteLine($"Broadcast: {message}");
break;
default:
Console.WriteLine($"Unknown notification: {request.Method}");
break;
}
};
await client.ConnectAsync("localhost", 8080);
Event-Driven Client Management:
using System.Collections.Concurrent;
using Voltaic;
McpWebsocketsServer server = new McpWebsocketsServer("localhost", 8080);
ConcurrentDictionary<string, ClientConnection> activeClients = new();
server.ClientConnected += (sender, client) =>
{
activeClients[client.SessionId] = client;
// Send welcome notification to the new client
JsonRpcRequest welcome = new JsonRpcRequest
{
Method = "welcome",
Params = new { message = $"Welcome {client.SessionId}!" }
};
client.Enqueue(welcome);
};
server.ClientDisconnected += (sender, client) =>
{
activeClients.TryRemove(client.SessionId, out _);
// Notify other clients
foreach (var otherClient in activeClients.Values)
{
JsonRpcRequest notification = new JsonRpcRequest
{
Method = "client_left",
Params = new { clientId = client.SessionId }
};
otherClient.Enqueue(notification);
}
};
await server.StartAsync();
Examples
Check out the src/Test.* projects for working examples:
- Test.JsonRpcServer / Test.JsonRpcClient: Interactive JSON-RPC demos over TCP
- Test.McpServer / Test.McpClient: MCP stdio examples
- Test.McpHttpServer / Test.McpHttpClient: MCP HTTP with SSE examples
- Test.McpWebsocketsServer / Test.McpWebsocketsClient: MCP WebSocket examples
- Test.Automated: Comprehensive test suite showing various usage patterns
Run examples:
# JSON-RPC Server (TCP)
dotnet run --project src/Test.JsonRpcServer/Test.JsonRpcServer.csproj -- 8080
# JSON-RPC Client (TCP)
dotnet run --project src/Test.JsonRpcClient/Test.JsonRpcClient.csproj -- 8080
# MCP Stdio Client (launches server subprocess)
dotnet run --project src/Test.McpClient/Test.McpClient.csproj
# MCP HTTP Server
dotnet run --project src/Test.McpHttpServer/Test.McpHttpServer.csproj -- 8080
# MCP HTTP Client
dotnet run --project src/Test.McpHttpClient/Test.McpHttpClient.csproj -- 8080
# MCP WebSocket Server
dotnet run --project src/Test.McpWebsocketsServer/Test.McpWebsocketsServer.csproj -- 8080
# MCP WebSocket Client
dotnet run --project src/Test.McpWebsocketsClient/Test.McpWebsocketsClient.csproj -- 8080
Connecting with MCP Inspector
The MCP Inspector is a visual tool for testing and debugging MCP servers. To connect MCP Inspector to a Voltaic MCP HTTP server:
Start your MCP HTTP server:
dotnet run --project src/Test.McpHttpServer/Test.McpHttpServer.csproj -- 8080Open MCP Inspector in your web browser
Configure the connection:
- Transport Type: Select
Streamable HTTP - URL: Enter
http://{hostname}:{port}/rpc- For example:
http://localhost:8080/rpc - If you specified a custom
rpcPathwhen creating the server, use that instead of/rpc
- For example:
- Transport Type: Select
Click Connect
Verify the connection: The inspector should display the list of registered tools and allow you to call them interactively
Note: MCP Inspector currently supports HTTP transport via Streamable HTTP. For other transports (TCP, WebSocket, stdio), use the corresponding client implementations or command-line tools.
Building
# Build everything
dotnet build src/Voltaic.sln
# Build the library
dotnet build src/Voltaic/Voltaic.csproj
# Run automated tests (all transports)
dotnet run --project src/Test.Automated/Test.Automated.csproj
# Run automated tests for specific transport
dotnet run --project src/Test.Automated/Test.Automated.csproj -- -stdio
dotnet run --project src/Test.Automated/Test.Automated.csproj -- -tcp
dotnet run --project src/Test.Automated/Test.Automated.csproj -- -http
dotnet run --project src/Test.Automated/Test.Automated.csproj -- -ws
# Run automated tests for multiple transports
dotnet run --project src/Test.Automated/Test.Automated.csproj -- -tcp -http -ws
License
Voltaic is released under the MIT License. Use it freely in your projects, commercial or otherwise.
Support
Need help or found a bug?
- Issues: Report bugs or request features at github.com/jchristn/voltaic/issues
- Discussions: Ask questions and share ideas at github.com/jchristn/voltaic/discussions
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Initial release