Skip to content
🐍 Looking for Python? See Python Capabilities | 📘 Looking for TypeScript? See TypeScript Capabilities

Capabilities System (Java/Spring Boot)

Named services that agents provide for discovery and dependency injection

Overview

Capabilities are named services that agents register with the mesh. When an agent declares a capability, other agents can discover and use it through dependency injection. Multiple agents can provide the same capability with different implementations.

Declaring Capabilities

Use @MeshTool to declare a capability on any method in your Spring Boot application:

@MeshTool(capability = "weather_data",
          description = "Provides weather info",
          version = "1.0.0",
          tags = {"weather", "current", "api"})
public WeatherResponse getWeather(
        @Param(value = "city", description = "City name") String city) {
    return new WeatherResponse(city, 72, "sunny");
}

record WeatherResponse(String city, int temp, String conditions) {}

Capability Selector Syntax

MCP Mesh uses the @Selector annotation for selecting capabilities. This same pattern appears in @MeshTool dependencies and in the @MeshLlm provider/filter. Spring web routes use @MeshDependency instead, with the same capability / tags / version fields.

Selector Fields

Field Required Description
capability Yes* Capability name to match
tags No Tag filters. Optional + (preferred) / - (excluded) operators
version No Semantic version constraint (e.g., >=2.0.0)

*When filtering by tags only (e.g., LLM tool filter), capability can be omitted.

Selector Usage

By capability name:

dependencies = @Selector(capability = "date_service")

With tag filters:

dependencies = @Selector(capability = "weather_data",
                          tags = {"+fast", "-deprecated"})

With version constraint:

dependencies = @Selector(capability = "api_client", version = ">=2.0.0")

Where Selectors Are Used

Context Example
@MeshTool dependencies dependencies = @Selector(capability = "svc")
@MeshLlm provider providerSelector = @Selector(capability = "llm")
@MeshLlm filter filter = @Selector(tags = {"tools"})
@MeshRoute dependencies dependencies = @MeshDependency(capability = "api", tags = {"+v2"})

Tag Operators

Prefix Meaning Example
(none) Required "api"
+ Preferred "+fast"
- Excluded "-deprecated"

Multiple Capabilities on One Agent

A single agent class can declare multiple capabilities:

@MeshAgent(name = "math-service", version = "1.0.0",
           description = "Math operations", port = 8080)
@SpringBootApplication
public class MathAgentApplication {

    @MeshTool(capability = "add",
              description = "Add two numbers",
              tags = {"math", "addition", "java"})
    public int add(@Param(value = "a", description = "First number") int a,
                   @Param(value = "b", description = "Second number") int b) {
        return a + b;
    }

    @MeshTool(capability = "multiply",
              description = "Multiply two numbers",
              tags = {"math", "multiplication", "java"})
    public int multiply(@Param(value = "a", description = "First number") int a,
                        @Param(value = "b", description = "Second number") int b) {
        return a * b;
    }
}

Multiple Implementations

Multiple agents can provide the same capability:

// Agent 1: Free weather provider
@MeshTool(capability = "weather_data",
          tags = {"weather", "openweather", "free"})
public WeatherResponse freeWeather(
        @Param(value = "city", description = "City name") String city) { /* ... */ }

// Agent 2: Premium weather provider
@MeshTool(capability = "weather_data",
          tags = {"weather", "premium", "accurate"})
public WeatherResponse premiumWeather(
        @Param(value = "city", description = "City name") String city) { /* ... */ }

Consumers select implementations using tag filters in @Selector:

@MeshTool(capability = "forecast",
          description = "Get forecast using premium weather",
          dependencies = @Selector(capability = "weather_data",
                                    tags = {"+premium"}))
public ForecastResponse getForecast(
        @Param(value = "city", description = "City name") String city,
        McpMeshTool<WeatherResponse> weatherData) {
    if (weatherData != null && weatherData.isAvailable()) {
        WeatherResponse weather = weatherData.call("city", city);
        return new ForecastResponse(weather);
    }
    return new ForecastResponse("Weather service unavailable");
}

Capability Resolution

When an agent requests a dependency, the registry resolves it by:

  1. Name matching: Find agents providing the requested capability
  2. Tag filtering: Apply tag constraints (if specified)
  3. Version constraints: Check semantic version compatibility
  4. Tiebreaker: Select exactly one winner from the survivors — highest tag score, then highest version, then agent ID

The registry does not load balance: it picks a single deterministic winner and holds it until the topology changes. See Tiebreaker.

Capability Naming Conventions

Pattern Example Use Case
noun_noun weather_data Data providers
verb_noun get_time Action services
domain_action auth_validate Domain-specific
service llm Generic services

A capability name is one or more dot-separated segments, each matching ^[a-zA-Z][a-zA-Z0-9_-]*$ — a leading letter followed by letters, digits, underscores, or hyphens, with no leading, trailing, or consecutive dots. Single-segment names like weather_data are the common case; dot-namespacing (media.caption, billing.v2.invoice) is the convention for grouping related capabilities under a service prefix. meshctl list --services and the meshui agent-detail view render dotted capabilities as grouped services — display-only, derived entirely from the name.

Versioning

Capabilities support semantic versioning:

@MeshTool(capability = "api_client", version = "2.1.0",
          description = "API client v2", tags = {"api", "v2"})
public ApiResponse callApi(
        @Param(value = "endpoint", description = "API endpoint") String endpoint) {
    /* ... */
}

Consumers can specify version constraints:

dependencies = @Selector(capability = "api_client", version = ">=2.0.0")

See Also

  • meshctl man tags --java - Tag matching system
  • meshctl man dependency-injection --java - How DI works
  • meshctl man decorators --java - All Java annotations