Skip to content
🐍 Looking for Python? See Python Capabilities | Looking for Java? See Java Capabilities

Capabilities System (TypeScript)

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.

Capability Selector Syntax

MCP Mesh uses a unified syntax for selecting capabilities throughout the framework. This same pattern appears in dependencies, mesh.llm() provider/filter, mesh.route(), and meshctl scaffold --filter.

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.

Syntax Forms

Shorthand (capability name only):

dependencies: ["date_service", "weather_data"];

Full form (with filters):

dependencies: [
  { capability: "date_service" },
  { capability: "weather_data", tags: ["+fast", "-deprecated"] },
  { capability: "api_client", version: ">=2.0.0" },
];

Where This Syntax Is Used

Context Example
addTool() dependencies dependencies: ["svc"] or [{ capability: "svc" }]
mesh.llm() provider provider: { capability: "llm", tags: ["+claude"] }
mesh.llm() filter filter: [{ capability: "calc" }, { tags: ["tools"] }]
mesh.route() dependencies [{ capability: "api", tags: ["+v2"] }]
meshctl scaffold --filter --filter '[{"capability": "x"}]'

Tag Operators

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

Selector Logic (AND/OR)

Syntax Semantics
tags: ["a", "b", "c"] a AND b AND c (all required)
tags: ["+a", "+b"] Prefer a, prefer b (neither required)
tags: ["a", "-x"] Must have a, must NOT have x
tags: ["a", ["b", "c"]] a AND (b OR c) - tag-level OR
tags: [["a"], ["b"]] a OR b (full OR)
[{tags:["a"]}, {tags:["b"]}] a OR b (multiple selectors - LLM filter)

Tag-Level OR:

Use nested arrays in tags for OR alternatives with fallback behavior:

dependencies: [
  // Prefer python implementation, fallback to typescript
  { capability: "math", tags: ["addition", ["python", "typescript"]] },
];

Resolution order:

  1. Try to find provider with addition AND python tags
  2. If not found, try provider with addition AND typescript tags
  3. If neither found, dependency is unresolved

See meshctl man tags for detailed tag matching behavior.

Declaring Capabilities

import { z } from "zod";

agent.addTool({
  name: "get_weather",
  capability: "weather_data", // Capability name
  description: "Provides weather info", // Human-readable description
  version: "1.0.0", // Semantic version
  tags: ["weather", "current", "api"], // Tags for filtering
  parameters: z.object({
    city: z.string(),
  }),
  execute: async ({ city }) => {
    return JSON.stringify({ city, temp: 72, conditions: "sunny" });
  },
});

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.

Multiple Implementations

Multiple agents can provide the same capability:

// Agent 1: OpenWeather implementation
agent1.addTool({
  name: "openweather",
  capability: "weather_data",
  tags: ["weather", "openweather", "free"],
  parameters: z.object({ city: z.string() }),
  execute: async ({ city }) => {
    /* ... */
  },
});

// Agent 2: Premium weather implementation
agent2.addTool({
  name: "premium_weather",
  capability: "weather_data",
  tags: ["weather", "premium", "accurate"],
  parameters: z.object({ city: z.string() }),
  execute: async ({ city }) => {
    /* ... */
  },
});

Consumers can select implementations using tag filters:

agent.addTool({
  name: "get_forecast",
  capability: "forecast",
  dependencies: [{ capability: "weather_data", tags: ["+premium"] }],
  parameters: z.object({}),
  execute: async ({}, weather_data: McpMeshTool | null = null) => {
    if (weather_data) {
      return await weather_data({ city: "NYC" });
    }
    return "Weather service unavailable";
  },
});

Dependency Declaration

Simple (by name)

agent.addTool({
  name: "my_tool",
  capability: "my_capability",
  dependencies: ["date_service", "weather_data"],
  parameters: z.object({ query: z.string() }),
  execute: async (
    { query },
    date_service: McpMeshTool | null = null,  // dependencies[0]
    weather_data: McpMeshTool | null = null,  // dependencies[1]
  ) => {
    // date_service and weather_data are McpMeshTool | null
  },
});

Advanced (with filters)

agent.addTool({
  name: "my_tool",
  capability: "my_capability",
  dependencies: [
    { capability: "date_service" },
    { capability: "weather_data", tags: ["+accurate", "-deprecated"] },
  ],
  parameters: z.object({ query: z.string() }),
  execute: async (
    { query },
    date_service: McpMeshTool | null = null,  // dependencies[0]
    weather_data: McpMeshTool | null = null,  // dependencies[1]
  ) => {
    // Dependencies injected positionally in declaration order
  },
});

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.

The TypeScript SDK performs no local capability-name validation — it forwards capability strings to the registry as-is, so a malformed name is rejected at registration time by the registry, not by the TS runtime. The segment-wise format above is the contract the registry enforces.

Versioning

Capabilities support semantic versioning:

agent.addTool({
  name: "api_v2",
  capability: "api_client",
  version: "2.1.0",
  // ...
});

Consumers can specify version constraints:

dependencies: [{ capability: "api_client", version: ">=2.0.0" }];

See Also

  • meshctl man tags --typescript - Tag matching system
  • meshctl man dependency-injection --typescript - How DI works
  • meshctl man decorators --typescript - All TypeScript functions