# java-sdk
**Repository Path**: yanfei133/java-sdk
## Basic Information
- **Project Name**: java-sdk
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-03-11
- **Last Updated**: 2026-03-11
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# ACP Java SDK
> **Documentation**: https://springaicommunity.mintlify.app/acp-java-sdk | [API Reference](https://springaicommunity.mintlify.app/acp-java-sdk/reference/java) | [Tutorial](https://springaicommunity.mintlify.app/acp-java-sdk/tutorial)
Pure Java implementation of the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) specification for building both clients and agents.
## Overview
The Agent Client Protocol (ACP) standardizes communication between code editors and coding agents. This SDK provides two modules:
- **Client** — connect to and interact with ACP-compliant agents
- **Agent** — build ACP-compliant agents in Java
Three API styles for building agents:
| Style | Best for | Example |
|-------|----------|---------|
| [**Annotation-based**](#2-hello-world-agent-annotation-based) | Least boilerplate — `@AcpAgent`, `@Prompt` annotations | [Jump to example](#2-hello-world-agent-annotation-based) |
| [**Sync**](#3-hello-world-agent-sync) | Simple blocking handlers with plain return values | [Jump to example](#3-hello-world-agent-sync) |
| [**Async**](#4-hello-world-agent-async) | Reactive applications using Project Reactor `Mono` | [Jump to example](#4-hello-world-agent-async) |
**Key Features:**
- Java 17+, type-safe, stdio and WebSocket transports
- Capability negotiation and structured error handling
- For a hands-on walkthrough, see the **[ACP Java Tutorial](https://github.com/markpollack/acp-java-tutorial)**
## Installation
Snapshot builds are published to Maven Central Snapshots. Add the snapshot repository and dependency:
```xml
central-snapshots
https://central.sonatype.com/repository/maven-snapshots/
true
false
com.agentclientprotocol
acp-core
0.9.0-SNAPSHOT
```
For annotation-based agent development:
```xml
com.agentclientprotocol
acp-agent-support
0.9.0-SNAPSHOT
```
For WebSocket server support (agents accepting WebSocket connections):
```xml
com.agentclientprotocol
acp-websocket-jetty
0.9.0-SNAPSHOT
```
---
## Getting Started
### 1. Hello World Client
Connect to an ACP agent and send a prompt ([tutorial](https://github.com/markpollack/acp-java-tutorial/tree/main/module-01-first-contact)):
```java
import com.agentclientprotocol.sdk.client.*;
import com.agentclientprotocol.sdk.client.transport.*;
import com.agentclientprotocol.sdk.spec.AcpSchema.*;
import java.util.List;
// Launch Gemini CLI as an ACP agent subprocess
var params = AgentParameters.builder("gemini").arg("--experimental-acp").build();
var transport = new StdioAcpClientTransport(params);
// Create client — sessionUpdateConsumer prints the agent's streamed response
AcpSyncClient client = AcpClient.sync(transport)
.sessionUpdateConsumer(notification -> {
if (notification.update() instanceof AgentMessageChunk msg) {
System.out.print(((TextContent) msg.content()).text());
}
})
.build();
// Three-phase lifecycle: initialize → session → prompt
client.initialize();
var session = client.newSession(new NewSessionRequest("/workspace", List.of()));
var response = client.prompt(new PromptRequest(
session.sessionId(),
List.of(new TextContent("What is 2+2? Reply with just the number."))
));
// Output: 4
// Stop reason: END_TURN
System.out.println("\nStop reason: " + response.stopReason());
client.close();
```
### 2. Hello World Agent (Annotation-Based)
The simplest way to build an agent — use annotations ([tutorial](https://github.com/markpollack/acp-java-tutorial/tree/main/module-12-echo-agent)):
```java
import com.agentclientprotocol.sdk.annotation.*;
import com.agentclientprotocol.sdk.agent.SyncPromptContext;
import com.agentclientprotocol.sdk.agent.support.AcpAgentSupport;
import com.agentclientprotocol.sdk.spec.AcpSchema.*;
@AcpAgent
class HelloAgent {
@Initialize
InitializeResponse init() {
return InitializeResponse.ok();
}
@NewSession
NewSessionResponse newSession() {
return new NewSessionResponse(UUID.randomUUID().toString(), null, null);
}
@Prompt
PromptResponse prompt(PromptRequest req, SyncPromptContext ctx) {
ctx.sendMessage("Hello from the agent!");
return PromptResponse.endTurn();
}
}
// Bootstrap and run
AcpAgentSupport.create(new HelloAgent())
.transport(new StdioAcpAgentTransport())
.run();
```
### 3. Hello World Agent (Sync)
The builder API with blocking handlers and plain return values ([tutorial](https://github.com/markpollack/acp-java-tutorial/tree/main/module-13-agent-handlers)):
```java
import com.agentclientprotocol.sdk.agent.*;
import com.agentclientprotocol.sdk.agent.transport.*;
import com.agentclientprotocol.sdk.spec.AcpSchema.*;
import java.util.UUID;
var transport = new StdioAcpAgentTransport();
// Sync agent — plain return values, no Mono
AcpSyncAgent agent = AcpAgent.sync(transport)
.initializeHandler(req -> InitializeResponse.ok())
.newSessionHandler(req ->
new NewSessionResponse(UUID.randomUUID().toString(), null, null))
.promptHandler((req, context) -> {
context.sendMessage("Hello from the agent!"); // blocking void method
return PromptResponse.endTurn();
})
.build();
agent.run(); // Blocks until client disconnects
```
### 4. Hello World Agent (Async)
For reactive applications, use the async API with Project Reactor ([tutorial](https://github.com/markpollack/acp-java-tutorial/tree/main/module-22-async-agent)):
```java
import com.agentclientprotocol.sdk.agent.*;
import com.agentclientprotocol.sdk.agent.transport.*;
import com.agentclientprotocol.sdk.spec.AcpSchema.*;
import reactor.core.publisher.Mono;
import java.util.UUID;
var transport = new StdioAcpAgentTransport();
// Async agent — handlers return Mono
AcpAsyncAgent agent = AcpAgent.async(transport)
.initializeHandler(req -> Mono.just(InitializeResponse.ok()))
.newSessionHandler(req -> Mono.just(
new NewSessionResponse(UUID.randomUUID().toString(), null, null)))
.promptHandler((req, context) ->
context.sendMessage("Hello from the agent!")
.then(Mono.just(PromptResponse.endTurn())))
.build();
agent.start().then(agent.awaitTermination()).block();
```
---
## Progressive Examples
### 5. Streaming Updates
Send real-time updates to the client during prompt processing (tutorial: [client-side](https://github.com/markpollack/acp-java-tutorial/tree/main/module-05-streaming-updates), [agent-side](https://github.com/markpollack/acp-java-tutorial/tree/main/module-14-sending-updates)).
**Annotation-based:**
```java
@Prompt
PromptResponse prompt(PromptRequest req, SyncPromptContext ctx) {
ctx.sendThought("Thinking...");
ctx.sendMessage("Here's my response.");
return PromptResponse.endTurn();
}
```
**Sync:**
```java
.promptHandler((req, context) -> {
context.sendThought("Thinking...");
context.sendMessage("Here's my response.");
return PromptResponse.endTurn();
})
```
**Async:**
```java
.promptHandler((req, context) ->
context.sendThought("Thinking...")
.then(context.sendMessage("Here's my response."))
.then(Mono.just(PromptResponse.endTurn())))
```
**Client - receiving updates:**
```java
AcpSyncClient client = AcpClient.sync(transport)
.sessionUpdateConsumer(notification -> {
var update = notification.update();
if (update instanceof AgentMessageChunk msg) {
System.out.print(((TextContent) msg.content()).text());
}
})
.build();
```
### 6. Agent-to-Client Requests
Agents can request file operations from the client ([tutorial](https://github.com/markpollack/acp-java-tutorial/tree/main/module-15-agent-requests)). The `context` parameter provides access to all agent capabilities.
**Agent (Sync) - reading files:**
```java
AcpSyncAgent agent = AcpAgent.sync(transport)
.promptHandler((req, context) -> {
// Convenience methods on SyncPromptContext
String content = context.readFile("pom.xml");
context.writeFile("output.txt", "Hello!");
return PromptResponse.endTurn();
})
.build();
agent.run();
```
**Client - registering file handlers:**
```java
AcpSyncClient client = AcpClient.sync(transport)
.readTextFileHandler((ReadTextFileRequest req) -> {
// Handlers receive typed requests directly
String content = Files.readString(Path.of(req.path()));
return new ReadTextFileResponse(content);
})
.writeTextFileHandler((WriteTextFileRequest req) -> {
Files.writeString(Path.of(req.path()), req.content());
return new WriteTextFileResponse();
})
.build();
```
### 7. Capability Negotiation
Check what features the peer supports before using them ([tutorial](https://github.com/markpollack/acp-java-tutorial/tree/main/module-17-capability-negotiation)):
```java
// Client: check agent capabilities after initialize
client.initialize(new InitializeRequest(1, clientCaps));
NegotiatedCapabilities agentCaps = client.getAgentCapabilities();
if (agentCaps.supportsLoadSession()) {
// Agent supports session persistence
}
if (agentCaps.supportsImageContent()) {
// Agent can handle image content in prompts
}
```
```java
// Agent: check client capabilities before requesting operations
NegotiatedCapabilities clientCaps = agent.getClientCapabilities();
if (clientCaps.supportsReadTextFile()) {
agent.readTextFile(...);
} else {
// Client doesn't support file reading - handle gracefully
}
// Or use require methods (throws AcpCapabilityException if not supported)
clientCaps.requireWriteTextFile();
agent.writeTextFile(...);
```
### 8. Error Handling
Handle protocol errors with structured exceptions ([tutorial](https://github.com/markpollack/acp-java-tutorial/tree/main/module-11-error-handling)):
```java
import com.agentclientprotocol.sdk.error.*;
try {
client.prompt(request);
} catch (AcpProtocolException e) {
if (e.isConcurrentPrompt()) {
// Another prompt is already in progress
} else if (e.isMethodNotFound()) {
// Agent doesn't support this method
}
System.err.println("Error " + e.getCode() + ": " + e.getMessage());
} catch (AcpCapabilityException e) {
// Tried to use a capability the peer doesn't support
System.err.println("Capability not supported: " + e.getCapability());
} catch (AcpConnectionException e) {
// Transport-level connection error
}
```
### 9. WebSocket Transport
Use WebSocket instead of stdio for network-based communication:
**Client (JDK-native, no extra dependencies):**
```java
import com.agentclientprotocol.sdk.client.transport.WebSocketAcpClientTransport;
import java.net.URI;
var transport = new WebSocketAcpClientTransport(
URI.create("ws://localhost:8080/acp"),
McpJsonMapper.getDefault()
);
AcpSyncClient client = AcpClient.sync(transport).build();
```
**Agent (requires acp-websocket-jetty module):**
```java
import com.agentclientprotocol.sdk.agent.transport.WebSocketAcpAgentTransport;
var transport = new WebSocketAcpAgentTransport(
8080, // port
"/acp", // path
McpJsonMapper.getDefault()
);
AcpAsyncAgent agent = AcpAgent.async(transport)
// ... handlers ...
.build();
agent.start().block(); // Starts WebSocket server on port 8080
```
---
## API Reference
### Packages
| Package | Description |
|---------|-------------|
| `com.agentclientprotocol.sdk.spec` | Protocol types (`AcpSchema.*`) |
| `com.agentclientprotocol.sdk.client` | Client SDK (`AcpClient`, `AcpAsyncClient`, `AcpSyncClient`) |
| `com.agentclientprotocol.sdk.agent` | Agent SDK (`AcpAgent`, `AcpAsyncAgent`, `AcpSyncAgent`) |
| `com.agentclientprotocol.sdk.agent.support` | Annotation-based agent runtime (`AcpAgentSupport`) |
| `com.agentclientprotocol.sdk.annotation` | Agent annotations (`@AcpAgent`, `@Prompt`, etc.) |
| `com.agentclientprotocol.sdk.capabilities` | Capability negotiation (`NegotiatedCapabilities`) |
| `com.agentclientprotocol.sdk.error` | Exceptions (`AcpProtocolException`, `AcpCapabilityException`) |
### Maven Artifacts
| Artifact | Description |
|----------|-------------|
| [`acp-core`](https://central.sonatype.com/artifact/com.agentclientprotocol/acp-core) | Client and Agent SDKs, stdio and WebSocket client transports |
| [`acp-annotations`](https://central.sonatype.com/artifact/com.agentclientprotocol/acp-annotations) | `@AcpAgent`, `@Prompt`, and other annotations |
| [`acp-agent-support`](https://central.sonatype.com/artifact/com.agentclientprotocol/acp-agent-support) | Annotation-based agent runtime |
| [`acp-test`](https://central.sonatype.com/artifact/com.agentclientprotocol/acp-test) | In-memory transport and mock utilities for testing |
| [`acp-websocket-jetty`](https://central.sonatype.com/artifact/com.agentclientprotocol/acp-websocket-jetty) | Jetty-based WebSocket server transport for agents |
### Transports
| Transport | Client | Agent | Module |
|-----------|--------|-------|--------|
| Stdio | `StdioAcpClientTransport` | `StdioAcpAgentTransport` | acp-core |
| WebSocket | `WebSocketAcpClientTransport` | `WebSocketAcpAgentTransport` | acp-core / acp-websocket-jetty |
---
## Building
```bash
./mvnw compile # Compile
./mvnw test # Run unit tests (258 tests)
./mvnw verify # Run unit tests + integration tests
./mvnw install # Install to local Maven repository
```
### Integration Tests
Integration tests connect to real ACP agents and require additional setup:
```bash
# Gemini CLI integration tests (requires API key and gemini CLI)
export GEMINI_API_KEY=your_key_here
./mvnw verify -pl acp-core
```
**Test Categories:**
| Type | Command | Count | Requirements |
|------|---------|-------|--------------|
| Unit tests | `./mvnw test` | 258 | None |
| Clean shutdown IT | `./mvnw verify` | 4 | None |
| Gemini CLI IT | `./mvnw verify` | 5 | `GEMINI_API_KEY`, `gemini` CLI in PATH |
## Testing Your Code
Use the mock utilities for testing:
```java
import com.agentclientprotocol.sdk.test.*;
// Create in-memory transport pair for testing
InMemoryTransportPair pair = InMemoryTransportPair.create();
// Use pair.clientTransport() for client, pair.agentTransport() for agent
MockAcpClient mockClient = MockAcpClient.builder(pair.clientTransport())
.fileContent("/test.txt", "test content")
.build();
```
---
## Tutorial
For a hands-on, progressive introduction to the SDK, see the **[ACP Java Tutorial](https://github.com/markpollack/acp-java-tutorial)** -- 30 modules covering client basics, agent development, streaming, testing, and IDE integration.
## ACP Ecosystem
This SDK is part of the [Agent Client Protocol](https://agentclientprotocol.com/) ecosystem.
**Other ACP SDKs:** [Kotlin](https://github.com/agentclientprotocol/kotlin-sdk) | [Python](https://github.com/agentclientprotocol/python-sdk) | [TypeScript](https://github.com/agentclientprotocol/typescript-sdk) | [Rust](https://github.com/agentclientprotocol/rust-sdk)
**Editor ACP docs:** [Zed](https://zed.dev/docs/ai/external-agents) | [JetBrains](https://www.jetbrains.com/help/ai-assistant/acp.html) | [VS Code](https://github.com/formulahendry/vscode-acp)
**ACP directories:** [Agents](https://agentclientprotocol.com/overview/agents) | [Clients](https://agentclientprotocol.com/overview/clients) | [Protocol spec](https://agentclientprotocol.com/protocol/overview)
## Roadmap
### v0.9.0 (Current)
- Client and Agent SDKs with async/sync APIs
- Stdio and WebSocket transports
- Capability negotiation
- Structured error handling
- Full protocol compliance (all SessionUpdate types, MCP configs, `_meta` extensibility)
- Snapshot builds published to Maven Central Snapshots
- 258 tests
### v1.0.0 (Planned)
- Stable release published to Maven Central
- Production hardening
- Performance optimizations