dotacp.client 2026.5.10

dotnet add package dotacp.client --version 2026.5.10
                    
NuGet\Install-Package dotacp.client -Version 2026.5.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="dotacp.client" Version="2026.5.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="dotacp.client" Version="2026.5.10" />
                    
Directory.Packages.props
<PackageReference Include="dotacp.client" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add dotacp.client --version 2026.5.10
                    
#r "nuget: dotacp.client, 2026.5.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package dotacp.client@2026.5.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=dotacp.client&version=2026.5.10
                    
Install as a Cake Addin
#tool nuget:?package=dotacp.client&version=2026.5.10
                    
Install as a Cake Tool

dotacp.client

.NET library for implementing Agent Client Protocol (ACP) clients (editors/IDEs).

What is dotacp.client?

This package provides the tools needed to integrate ACP agent support into editors, IDEs, and other client applications. It includes:

  • IAcpClient Interface: Core interface defining all client-side protocol handlers
  • Connection Management: Handles JSON-RPC communication with ACP agents
  • RPC Message Routing: Automatic dispatch of inbound agent requests

Dependencies

  • .NET Standard 2.0 or higher
  • dotacp.protocol - Protocol type definitions
  • StreamJsonRpc (v2.7.76+) - JSON-RPC communication

Installation

dotnet add package dotacp.client

Or reference the project directly:

<ItemGroup>
    <ProjectReference Include="path/to/client/client.csproj" />
</ItemGroup>

Quick Start

1. Implement the IAcpClient Interface

using dotacp.client;
using dotacp.protocol;
using System.Threading;
using System.Threading.Tasks;

public class MyAcpClient : IAcpClient
{
    public async Task<RequestPermissionResponse> RequestPermissionAsync(
        RequestPermissionRequest request,
        CancellationToken cancellationToken = default)
    {
        // Show permission dialog to user using request.Options and request.ToolCall details
        var userOption = await ShowPermissionDialogAsync(
            request.Options,
            request.ToolCall);

        return new RequestPermissionResponse
        {
            Outcome = userOption != null 
                ? (RequestPermissionOutcome)new SelectedPermissionOutcome { OptionId = userOption.OptionId }
                : new RequestPermissionOutcomeCancelled()
        };
    }

    public async Task SessionUpdateAsync(
        SessionNotification notification,
        CancellationToken cancellationToken = default)
    {
        // Handle session state updates from agent
        // Update UI, logs, etc.
        Console.WriteLine($"Session {notification.SessionId} updated");
    }

    public async Task<WriteTextFileResponse> WriteTextFileAsync(
        WriteTextFileRequest request,
        CancellationToken cancellationToken = default)
    {
        try
        {
            // Write file to disk using the client's file system
            // request.SessionId, request.Path, and request.Content are available
            await File.WriteAllTextAsync(
                request.Path,
                request.Content,
                cancellationToken);

            return new WriteTextFileResponse();
        }
        catch (Exception ex)
        {
            // Throw exception to indicate error to the agent
            throw new InvalidOperationException($"Failed to write file {request.Path}: {ex.Message}");
        }
    }

    public async Task<ReadTextFileResponse> ReadTextFileAsync(
        ReadTextFileRequest request,
        CancellationToken cancellationToken = default)
    {
        try
        {
            // Read file from disk (request.Path available)
            var content = await File.ReadAllTextAsync(
                request.Path,
                cancellationToken);

            return new ReadTextFileResponse
            {
                Content = content
            };
        }
        catch (Exception ex)
        {
            // Throw exception to indicate error to the agent
            throw new InvalidOperationException($"Failed to read file {request.Path}: {ex.Message}");
        }
    }

    public async Task<CreateTerminalResponse> CreateTerminalAsync(
        CreateTerminalRequest request,
        CancellationToken cancellationToken = default)
    {
        // Create a new terminal/shell session
        // request.SessionId, request.Command, request.Args, request.Cwd, request.Env available
        var terminalId = Guid.NewGuid().ToString();
        
        // Start the terminal process
        var process = new Process
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = request.Command,
                Arguments = string.Join(" ", request.Args ?? Array.Empty<string>()),
                WorkingDirectory = request.Cwd,
                UseShellExecute = false,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                CreateNoWindow = true
            }
        };

        process.Start();

        return new CreateTerminalResponse
        {
            TerminalId = terminalId
        };
    }

    public async Task<TerminalOutputResponse> TerminalOutputAsync(
        TerminalOutputRequest request,
        CancellationToken cancellationToken = default)
    {
        // Get output from the terminal (request.SessionId, request.TerminalId available)
        // Return the captured output and exit status if available
        return new TerminalOutputResponse
        {
            Output = "Terminal output here",
            Truncated = false,
            ExitStatus = null  // null if still running
        };
    }

    public async Task<ReleaseTerminalResponse> ReleaseTerminalAsync(
        ReleaseTerminalRequest request,
        CancellationToken cancellationToken = default)
    {
        // Release/close a terminal
        // Clean up the terminal process if needed
        return new ReleaseTerminalResponse { };
    }

    public async Task<WaitForTerminalExitResponse> WaitForTerminalExitAsync(
        WaitForTerminalExitRequest request,
        CancellationToken cancellationToken = default)
    {
        // Wait for terminal process to exit
        // Return exit code
        return new WaitForTerminalExitResponse { ExitCode = 0 };
    }

    public async Task<KillTerminalResponse> KillTerminalAsync(
        KillTerminalRequest request,
        CancellationToken cancellationToken = default)
    {
        // Kill/terminate a terminal process
        return new KillTerminalResponse { };
    }

    public async Task<object> ExtMethodAsync(
        string method,
        object request,
        CancellationToken cancellationToken = default)
    {
        // Handle custom extension methods specific to your client
        throw new NotImplementedException($"Unknown extension method: {method}");
    }

    public async Task ExtNotificationAsync(
        string method,
        object notification,
        CancellationToken cancellationToken = default)
    {
        // Handle custom extension notifications
        Console.WriteLine($"Extension notification: {method}");
    }

    private async Task<PermissionOption> ShowPermissionDialogAsync(
        PermissionOption[] options,
        ToolCallUpdate toolCall)
    {
        // Implementation depends on your UI framework
        // Display toolCall.Title and options to user
        // Return the selected option or null to deny
        return options.FirstOrDefault();
    }
}

2. Connect to an Agent

using System.Diagnostics;

// Start the agent process
var agentProcess = Process.Start(new ProcessStartInfo
{
    FileName = "my-agent.exe",
    UseShellExecute = false,
    RedirectStandardInput = true,
    RedirectStandardOutput = true
});

// Create client implementation
var client = new MyAcpClient();

// Connect to the agent
var connection = Connection.RunClient(
    client,
    agentProcess.StandardInput.BaseStream,
    agentProcess.StandardOutput.BaseStream);

if (connection == null)
{
    Console.WriteLine("Failed to connect to agent");
    return;
}

// Initialize the protocol
var initResponse = await connection.InitializeAsync(
    new InitializeRequest
    {
        ProtocolVersion = ProtocolMeta.Version,
        ClientCapabilities = new ClientCapabilities
        {
            Fs = new FileSystemCapability
            {
                ReadTextFile = true,
                WriteTextFile = true
            },
            Terminal = true
        }
    });

Console.WriteLine($"Agent initialized with version {initResponse.ProtocolVersion}");

// Authenticate
var authResponse = await connection.AuthenticateAsync(
    new AuthenticateRequest
    {
        MethodId = "auth-method-1"  // Use method ID advertised by agent
    });

// Create a new session
var sessionResponse = await connection.NewSessionAsync(
    new NewSessionRequest
    {
        Cwd = Directory.GetCurrentDirectory(),
        McpServers = Array.Empty<McpServer>()
    });

var sessionId = sessionResponse.SessionId;

// Send prompts to the agent
var promptResponse = await connection.PromptAsync(
    new PromptRequest
    {
        SessionId = sessionId,
        Prompt = new ContentBlock[]
        {
            new TextContent { Text = "Help me refactor this function" }
        }
    });

Console.WriteLine($"Agent processing stopped: {promptResponse.StopReason}");

Protocol Request Handlers

Your client implementation must handle the following agent requests:

File Operations

  • fs/read_text_file - Agent requests to read file content
  • fs/write_text_file - Agent requests to write files

Permission Requests

  • session/request_permission - Agent asks for permission to perform actions
    • Can request file modifications, terminal creation, etc.

Session Updates

  • session/update - Agent sends session state updates and notifications

Terminal Management

  • terminal/create - Create a new terminal/shell
  • terminal/output - Send output to a terminal
  • terminal/release - Close/release a terminal
  • terminal/wait_for_exit - Wait for terminal process to exit
  • terminal/kill - Kill/terminate a terminal

Best Practices

  1. Error Handling: Always catch exceptions and return appropriate error responses
  2. User Permissions: Prompt users for sensitive operations (file writes, terminal creation)
  3. File Access: Restrict agent file access to appropriate directories
  4. Cancellation: Respect CancellationToken for responsive UI
  5. Logging: Log all agent interactions for debugging
  6. Security: Validate agent requests before execution
  7. Resource Management: Properly clean up processes and file handles

License

Licensed under the Apache License 2.0. See the LICENSE file for details.

See Also

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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 is compatible.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 is compatible.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2026.5.10 102 5/10/2026
2026.3.18 108 3/18/2026
2026.3.12-beta.1 71 3/12/2026
0.1.0-beta.2 62 3/9/2026
0.1.0-beta.1 61 3/5/2026
0.1.0-alpha.4 63 3/3/2026
0.1.0-alpha.3 60 3/2/2026
0.1.0-alpha.2 62 3/2/2026
0.1.0-alpha.1 69 3/1/2026