Java Example of Google's UCP

Universal Communication Protocol for AI Agents

Google UCP Agent-to-Agent

Overview

This project demonstrates Java implementation of Google's UCP (Universal Communication Protocol) which is an emerging agent-to-agent interoperability protocol designed to let AI agents built by different vendors communicate, discover capabilities, exchange context, and invoke actions in a standardized way. UCP focuses on capability discovery, identity, security, and structured message exchange, so agents can collaborate without tight coupling or proprietary integrations. In practice, it acts as a neutral "language" between agents, enabling ecosystems where tools, agents, and services can work together across platforms—similar in spirit to how HTTP standardized web communication, but specifically for autonomous and semi-autonomous AI agents. This AI Agent for UCP will be using tools4ai, a2ajava, and ucpjava as core libraries.

🔍 Capability Discovery

Platforms dynamically find business capabilities via profiles at /.well-known/ucp.

🔄 Transport Agnostic

Works across REST, MCP, and A2A protocols for maximum interoperability.

Why UCP Matters

Today's commerce ecosystem, platforms, businesses, payment providers, and credential providers operate on disparate systems, creating integration complexity and abandoned transactions. UCP addresses this fragmentation by providing:

Core Concepts

UCP Protocol Architecture

UCP addresses fragmented commerce by providing standardized interaction patterns through three key capabilities:

UCP Business

A UCP Business is the entity selling goods or services that acts as the Merchant of Record (MoR), retaining financial liability and ownership. In code, this is represented by the @UCPBusiness annotation.

Key Constraint: UCP enforces that each host represents exactly one merchant to maintain clear liability and ownership.

@UCPBusiness(name = "AutoGroup North", version = "2026-01-19")
public class ShoppingService implements UCPAware {
// Business implementation
}

UCP Capability

A UCP Capability is a standalone core feature that a business supports—the fundamental "verbs" of UCP. These are declared using @UCPCapability annotations and follow reverse-domain naming conventions.

Capability Namespace Patterns
Namespace Pattern Authority Example
dev.ucp.* UCP governing body dev.ucp.shopping.checkout
com.vendor.* Vendor organization com.example.payments.installments
io.github.* Custom implementations io.github.vishalmysore.car_booking
Standard UCP Capabilities

UCP defines several standard capabilities:

Capability Structure

All capabilities must include:

@UCPCapability(
name = "dev.ucp.shopping.checkout",
version = "2026-01-11",
spec = "https://ucp.dev/specification/checkout",
schema = "https://ucp.dev/schemas/shopping/checkout.json"
)
public Object createCheckout(Map checkoutRequest);

Implementation Architecture

What This Guide Covers

This implementation guide walks through building a complete UCP-compliant Java application that demonstrates:

Implementation Approach

The guide presents a practical, code-first approach using Spring Boot with the tools4ai framework, demonstrating how to:

Standard UCP Capabilities

UCPAware Interface

The UCPAware interface defines standard UCP capabilities that must be implemented for core commerce operations:

public interface UCPAware {

    @UCPCapability(
        name = "dev.ucp.shopping.checkout",
        version = "2026-01-11",
        spec = "https://ucp.dev/specification/checkout",
        schema = "https://ucp.dev/schemas/shopping/checkout.json"
    )
    Object createCheckout(Map checkoutRequest);

    @UCPCapability(
        name = "dev.ucp.shopping.order",
        version = "2026-01-11",
        spec = "https://ucp.dev/specification/order",
        schema = "https://ucp.dev/schemas/shopping/order.json"
    )
    Object getOrder(String orderId);

    @UCPCapability(
        name = "dev.ucp.common.identity_linking",
        version = "2026-01-11",
        spec = "https://ucp.dev/specification/identity-linking",
        schema = "https://ucp.dev/schemas/common/identity_linking.json"
    )
    Object linkIdentity(Map identityRequest);
}
Key Requirements

Custom Capabilities

Implementation Example: Car Booking

Custom capabilities allow businesses to extend UCP with domain-specific features while maintaining protocol compliance.

package io.github.vishalmysore.controllers;

import com.t4a.annotations.Action;
import com.t4a.annotations.Agent;
import com.t4a.processor.ProcessorAware;
import io.github.vishalmysore.a2ui.A2UIAware;
import io.github.vishalmysore.ucp.annotation.UCPCapability;
import io.github.vishalmysore.ucp.domain.SimpleUCPResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
* UCP Business for car booking
*
* IMPORTANT CONSTRAINTS:
* - Only one agent can have tag @UCPBusiness in our Spring Boot application
* - UCP Capabilities can only be in REST controllers (not services)
* - This is required because UCP mandates support for both REST and MCP transports
* - If it's a REST controller, the UCP manifest adds transport as "rest"
*/
@Agent(
groupName = "carbooking",
groupDescription = "car booking service",
prompt = "You are a car booking assistant. Help users book cars based on their preferences and requirements."
)
@RestController(value = "/carbooking")
public class CarbookingController implements ProcessorAware, A2UIAware {

@Action(description = "Book a car based on user preferences")
@UCPCapability(
name = "io.github.vishalmysore.car_booking",
version = "2026-01-19",
spec = "https://autogroup-north.com/specs/car-booking",
schema = "https://autogroup-north.com/schemas/booking.json"
)
@PostMapping("/bookCar")
public SimpleUCPResult bookCar(
String carType,
String pickupLocation,
String dropoffLocation,
String pickupDate,
String dropoffDate) {

// Booking logic here
Map bookingDetails = new HashMap<>();
bookingDetails.put("carType", carType);
bookingDetails.put("pickupLocation", pickupLocation);
bookingDetails.put("dropoffLocation", dropoffLocation);
bookingDetails.put("pickupDate", pickupDate);
bookingDetails.put("dropoffDate", dropoffDate);
bookingDetails.put("confirmationNumber", "ABC123XYZ");

return new SimpleUCPResult(bookingDetails);
}
}

Service Types & Patterns

Service Type Comparison

Service Type Annotation Transport Use Case
UCP Business @UCPBusiness + @RestController REST + MCP Standard commerce capabilities
Agentic Service @Agent MCP + A2A AI agent interactions

Agentic Service Example: Car Selling

Services that are NOT UCP capabilities but are available for AI agent interactions:

package io.github.vishalmysore.service;

import com.t4a.annotations.Action;
import com.t4a.annotations.Agent;
import com.t4a.processor.ProcessorAware;
import io.github.vishalmysore.a2ui.A2UIAware;

/**
* MCP Service for car selling
*
* IMPORTANT CONSTRAINTS:
* - This is NOT a UCP Business or UCP Capability
* - Only exposed via MCP and A2A protocols
* - Does NOT require REST endpoint
* - Cannot use @UCPCapability annotation (will throw error during startup)
*/
@Agent(
groupName = "carbooking",
groupDescription = "car booking service",
prompt = "You are a car booking assistant. Help users book cars based on their preferences and requirements."
)
public class CarSellingService implements ProcessorAware, A2UIAware {

/**
* This is an agentic action exposed only via MCP and A2A
* It is NOT a UCP business or capability
*/
@Action(description = "Sell a car based on user preferences")
// @UCPCapability(name = "io.github.vishalmysore.sell_car", ...)
// ⚠️ CANNOT uncomment above - will throw error:
// "UCP Violation: Agent CarSellingService must be annotated with
// @RestController to support REST transport"
public Object sellCar(
String carType,
String pickupLocation,
String dropoffLocation,
String pickupDate,
String dropoffDate) {

return "Car sold: " + carType + " from " + pickupLocation +
" to " + dropoffLocation + " between " + pickupDate +
" and " + dropoffDate;
}
}

Discovery & Endpoint Resolution

Generated UCP Manifest

The framework automatically generates a complete UCP discovery profile at /.well-known/ucp:

{
"ucp": {
"capabilities": [
{
"schema": "https://autogroup-north.com/schemas/inventory_search.json",
"name": "io.github.vishalmysore.inventory_search",
"version": "2026-01-19",
"spec": "https://autogroup-north.com/specs/inventory-search"
},
{
"schema": "https://ucp.dev/schemas/shopping/order.json",
"name": "dev.ucp.shopping.order",
"version": "2026-01-11",
"spec": "https://ucp.dev/specification/order"
},
{
"schema": "https://ucp.dev/schemas/shopping/checkout.json",
"name": "dev.ucp.shopping.checkout",
"version": "2026-01-11",
"spec": "https://ucp.dev/specification/checkout"
},
{
"schema": "https://autogroup-north.com/schemas/comparison.json",
"name": "io.github.vishalmysore.car_comparison",
"version": "2026-01-19",
"spec": "https://autogroup-north.com/specs/car-comparison"
},
{
"schema": "https://autogroup-north.com/schemas/booking.json",
"name": "io.github.vishalmysore.car_booking",
"version": "2026-01-19",
"spec": "https://autogroup-north.com/specs/car-booking"
},
{
"schema": "https://ucp.dev/schemas/common/identity_linking.json",
"name": "dev.ucp.common.identity_linking",
"version": "2026-01-11",
"spec": "https://ucp.dev/specification/identity-linking"
}
],
"services": {
"dev.ucp.shopping": {
"rest": {
"schema": "https://ucp.dev/services/shopping/openapi.json",
"endpoint": "http://localhost:7860/ucp/v1"
},
"mcp": {
"schema": "https://ucp.dev/services/shopping/mcp.openrpc.json",
"endpoint": "http://localhost:7860/ucp/mcp"
},
"version": "2026-01-11",
"spec": "https://ucp.dev/specification/overview"
}
},
"version": "2026-01-19"
}
}

Client Discovery Process

To discover the specific REST call for booking a car, the client follows this systematic Endpoint Resolution process:

  1. Identify the Vertical (Service): The client examines the services object. "Booking" or "Checkout" typically falls under the dev.ucp.shopping service.
  2. Fetch the Transport Schema: The client retrieves the OpenAPI specification from the rest.schema field.
  3. Match the Capability to the Path: The client sees the io.github.vishalmysore.car_booking capability is advertised.
  4. Resolve the Final URL: The client appends the OpenAPI path to the service endpoint.
  5. Construct the Payload (Schema Composition): This is the most critical step for custom capabilities.

API Examples

This section provides practical examples of how to interact with the UCP implementation using both MCP (Model Context Protocol) and UCP protocols.

MCP Tools List Example

The following curl command demonstrates how to list available tools using the MCP protocol:

curl -H "Content-Type: application/json" -d '{
    "jsonrpc": "2.0",
    "method": "tools/list",
    "params": {},
    "id": 1
}' http://localhost:7860/

MCP Tool Call Example

The following curl command demonstrates how to call the compareCar tool using the MCP protocol:

curl -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "compareCar",
    "arguments": {
      "provideAllValuesInPlainEnglish": "{\"car1\": \"Tesla Model 3\", \"car2\": \"BMW i4\"}"
    }
  }
}' http://localhost:7860/

Response:

{"result":{"content":[{"type":"text","annotations":null,"text":"Tesla Model 3 is better than BMW i4","type":"text"}],"textResult":"Tesla Model 3 is better than BMW i4"},"id":2,"jsonrpc":"2.0"}

UCP Protocol Example

The following curl command demonstrates how to use the UCP protocol for car booking:

curl -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "method": "io.github.vishalmysore.car_booking",
  "params": {
    "_meta": {
      "ucp": {
        "profile": "https://platform.example/profiles/v2026-01/shopping-agent.json"
      }
    },
    "car_model": "Toyota Camry",
    "booking_date": "2026-01-25",
    "customer_info": {
      "name": "John Doe",
      "email": "john@example.com"
    }
  },
  "id": 1
}' http://localhost:7860/ucp/mcp

Response:

{"result":{"ucp":{"capabilities":[{"name":"io.github.vishalmysore.car_booking","version":"2026-01-19"}],"version":"2026-01-11"},"carType":"Toyota Camry","confirmationNumber":"ABC123XYZ","dropoffDate":null,"dropoffLocation":null,"pickupDate":"2026-01-25","pickupLocation":null},"id":1,"jsonrpc":"2.0"}

Design Considerations

Annotation-Driven Approach

The annotation-driven approach in this UCP implementation provides automatic capability discovery, clean separation of concerns, and dual transport support.

Advantages
  1. Automatic Discovery: The UCPController automatically scans for @UCPCapability annotations and generates the discovery profile.
  2. Clean Architecture: The separation between @Agent services (MCP/A2A only) and @UCPBusiness controllers (REST + MCP).
  3. Type Safety: Annotations provide compile-time checking for capability names, version formats, and required fields.
Future Considerations

These are the areas for potential improvement which I will consider in future iterations:

  1. Validation Complexity: Annotation values (like YYYY-MM-DD version format) must be validated at runtime.
  2. Framework Coupling: The approach tightly couples business logic to UCP framework and Spring's annotation processing.
  3. Runtime Overhead: Annotation scanning at startup adds initialization time, though typically negligible.
Implementation Quality

Current implementation handles complexity well by:

The annotation approach is particularly effective for UCP because it maps naturally to the protocol's capability-based design and enables the dynamic discovery that UCP emphasizes.