CapMesh

Service Discovery for the Agentic World

Build, push, pull and resolve Agents, Tools and Skills -- like Docker, but for capabilities.

GitHub  |  pip install capmesh  |  Apache 2.0

Contents 1. Why CapMesh? 2. Core Concepts 3. CLI Reference -- Docker Commands Side-by-Side build / push / pull / tag / inspect / search resolve / providers / graph / login / server 4. Build Providers -- Complete Working Examples a) MCP Tool b) A2A Agent c) Skill d) REST Tool 5. Runtime API Endpoints -- What Providers Expose 6. Use Providers -- Resolve and Call a) Python SDK b) Raw HTTP API c) Using the Binding to Call the Service 7. Framework Integration -- Discover and Use Capabilities CrewAI | LangGraph | Strands | AutoGen | Google ADK | OpenAI | Semantic Kernel | Raw HTTP 8. Backward Compatibility -- Zero Code Changes to Providers 9. In Action -- Three Scenarios a) PR Review Pipeline b) Provider Swap c) Dynamic Discovery 10. Governance -- Policies, Visibility, Approval, Audit 11. API Reference 12. Getting Started

1 Why CapMesh?

Every agentic application today hardcodes which tools, agents, and services it calls. When a tool changes -- or when you need to swap GitHub for GitLab, or Snyk for Semgrep -- you hunt through code, update imports, rewrite tests, and redeploy. With a dozen agents, this is a crisis every quarter.

CapMesh solves this the way DNS solved IP address management: name what you need, not where it lives. Consumers ask for a capability ("security scan"). CapMesh returns the best available provider, enforcing governance, versioning, and environment isolation along the way. The consumer calls the provider directly using the returned binding. No proxy, no overhead.

Without CapMesh

from tools.github import GitHubReader
from tools.snyk import SnykScanner
from agents.crewai import SecurityAgent

# Every dependency is hardcoded.
# Change Snyk to Semgrep?  Rewrite + redeploy.
# Swap GitHub to GitLab?   Rewrite + redeploy.
# Restrict an intern?      Add middleware.
# Audit tool usage?        Not possible.

repo    = GitHubReader(token=SECRET)
scanner = SnykScanner(api_key=OTHER_SECRET)
agent   = SecurityAgent(endpoint=HARDCODED_URL)

With CapMesh

import capmesh

mesh = capmesh.connect()

# Consumers ask for WHAT, not WHO.
repo    = mesh.need("read a repository")
scanner = mesh.need("security vulnerability scan")
agent   = mesh.need("security code review", kind="agent")

# Swap provider?  One registry command.
# Restrict access? One YAML field.
# Audit trail?    Automatic.
Quick Start
import capmesh
mesh = capmesh.connect()

# Any type -- natural language
result = mesh.need("security scan")

# Only agents
agent = mesh.need("security scan", kind="agent")

# Only MCP tools
tool = mesh.need("read repo", kind="tool", protocol="mcp")
ChangeWithout CapMeshWith CapMesh
Swap GitHub for GitLab2-3 days: code + tests + deploy30 seconds: register new provider
Upgrade Snyk to Semgrep1-2 days30 seconds
Restrict intern to staging onlyDays: middleware + ACLsOne YAML field: environment: [staging]
Audit which tool was usedNot possible without custom loggingAutomatic: every resolution is traced
Add a new capability at runtimeImpossible without restart + redeployRegister + discoverable instantly
Pin a team to scanner v2.x onlyManual version gates in each repoversion_constraint: ">=2.0,<3.0"

The Real Cost of Hardcoded Tools

It's not just about swapping one tool. It's what happens at scale:

Your company has 15 agents across 4 teams. Each agent hardcodes its tools. Now:

This isn't hypothetical. It's happening in every org building with agents today.

What CapMesh Gives You

Late Binding

Agents bind to tools at resolution time, not at build time. Swap providers without touching agent code. Ever.

Dynamic Discovery

Register a new agent at 2pm. Every orchestrator discovers it at 2:01pm. No restart. No redeploy. No config change.

Natural Language

mesh.need("scan for security issues") — agents describe what they need in English. CapMesh finds who provides it.

Cross-Framework

LangGraph, CrewAI, Strands, AutoGen, Google ADK — all in one registry. Framework is metadata, not lock-in.

Type-Safe Filtering

kind="agent", protocol="mcp" — ask for exactly what you need. An MCP tool. An A2A agent. A Skill. Or search all.

Skill Dual Binding

Skills declare what they need, not which tool. CapMesh resolves the tools independently. Same skill works with any vendor.

Policy & Access Control

Visibility (public/org/private), environment isolation (staging vs prod), approval workflows — all in the manifest YAML.

Immutable Versions

Once published, a version can never be silently modified. sha256 digest verification. Tamper-proof by design.

Complete Audit Trail

Every resolution traced: who asked, what was available, what was selected, why others were rejected. Compliance-ready.

Version Pinning

mesh.need("scan", version=">=2.0,<3.0") — compliance says "only scanner v2 in prod"? One parameter. Deterministic.

Graceful Deprecation

Deprecate a provider — agents auto-fallback to the next best version. No emergency patches. No breaking changes.

Caching

Resolution cache with auto-invalidation. First call: 16ms. Repeated calls: 0ms. Cache clears automatically when registry changes.

The DNS Analogy

CapMesh is to agents what DNS is to IP addresses.

Before DNS: every application hardcoded IP addresses. Change a server? Update every client.
After DNS: applications use domain names. Move a server? Update one DNS record.

Before CapMesh: every agent hardcodes tool endpoints. Swap a tool? Update every agent.
After CapMesh: agents ask for capabilities. Swap a tool? Register one new provider.

Who Benefits

RoleWithout CapMeshWith CapMesh
Agent developers Import 5 tool SDKs, manage versions, handle auth per tool mesh.need("what I need") — one line, any tool
Platform teams Coordinate tool changes across 15 agent repos Register once in CapMesh. All agents discover automatically.
Security teams No visibility into which agents use which tools Full audit trail. Approval workflows. Environment isolation.
Compliance Manual tracking of tool usage Every resolution traced. Version pinning. Immutable digests.
Leadership "How many agents do we have? What can they do?" capmesh search "*" — complete capability catalog

2 Core Concepts

Two-Plane Architecture

Artifact Plane (Docker-inspired)

Build, push, pull, tag, inspect. Manages the lifecycle of providers as versioned, immutable artifacts with sha256 content digests. Same mental model as Docker images -- but for agents, tools, and skills.

Capability Plane (CapMesh differentiator)

Resolve, discover, bind. Maps a capability name to the best available provider through a 9-step deterministic pipeline: find candidates, apply policy, filter by version constraint, select highest semver, build binding, record trace.

Four Provider Types

TypeProtocolRuntime EndpointExample
MCP Tool MCP MCP (JSON-RPC) Server name registered in the MCP client (e.g., github-mcp) GitHub MCP server, filesystem-mcp
A2A Agent A2A A2A (HTTP) Full HTTPS URL the agent listens on (e.g., https://security-agent.acme.com) LangGraph reviewer, CrewAI analyst
REST Tool REST HTTP/REST Full API base URL (e.g., https://api.sonarcloud.io/v1) SonarCloud, Datadog, Twilio
Skill SKILL Skill (SKILL.md) Path to the SKILL.md file; CapMesh resolves tool deps separately Security review procedure, triage runbook
Key insight: CapMesh does NOT host your agents or tools. It is a registry and resolver -- like DNS. The provider runs wherever you want. CapMesh tells consumers where to find it and which one to use.

Architecture Diagram

Consumer (Your Agent / Pipeline) | | POST /v1/resolve {"capability": "security.code.review", "contract": "v1"} v +------------------------------- CapMesh Server ---------------------------------+ | | | Registry (SQLite) | | providers_for(capability, contract) | | | | | v | | Resolver Pipeline | | 1. find candidates -- all providers claiming this capability | | 2. filter revoked -- governance.status != revoked | | 3. health check -- liveness cache | | 4. contract match -- exact contract version (v1 != v2) | | 5. apply policy -- visibility, environment, owner | | 6. version constraint -- semver filter (e.g., >=2.0,<3.0) | | 7. select best -- highest semver among approved | | 8. build binding -- protocol-specific connection object | | 9. record trace -- SQLite trace with full candidate list | | | +------------------------------- Returns binding --------------------------------+ | | {protocol: "a2a", connection: {endpoint: "https://security-agent.acme.com"}} v Consumer calls the provider directly using the returned binding. CapMesh is NOT in the data path. Zero latency added to actual tool calls. Providers run wherever the PROVIDER team deploys them: +---------------------+ +---------------------+ +---------------------+ | A2A Agent | | MCP Server | | REST API | | https://agent.acme | | server name: | | https://api.sonar. | | | | github-mcp | | cloud.io/v1 | +---------------------+ +---------------------+ +---------------------+

3 CLI Reference -- Docker Commands Side-by-Side

CapMesh borrows Docker's mental model for the artifact plane. Every Docker workflow you know maps directly to a CapMesh command.

capmesh tool build  docker build

Validate a manifest and compute its content digest. Does not register it yet -- just proves the manifest is well-formed.

Docker

docker build -t myapp:1.0.0 .

CapMesh

capmesh tool build --directory ./github-reader/
capmesh agent build --directory ./security-agent/
capmesh skill build --directory ./code-review-skill/

Flags:

FlagDescriptionDefault
--directory, -dDirectory containing manifest.yaml.
--file, -fExplicit path to manifest.yaml--
--strictFail on any warningfalse

Example output -- building an MCP tool:

$ capmesh tool build --directory ./github-reader/ Validating manifest: ./github-reader/manifest.yaml [OK] Required fields present [OK] Capability IDs valid (repository.read, repository.search) [OK] Contract versions valid (v1) [OK] Semver valid (2.3.1) [OK] Governance fields present (status: approved) [OK] Interface fields present (protocol: mcp, server: github-mcp) Build summary Kind: tool Protocol: mcp Name: tools/github-reader Version: 2.3.1 Digest: sha256:7a3f9c12d8e5b024f1a6c3d9e7f2b841a0c5d3e8f9b2a7c4d1e6f3b0a8c5d2e9 Provides: repository.read/v1, repository.search/v1 Status: VALID -- ready to push

capmesh tool push  docker push

Register (push) a validated provider into the CapMesh registry. Equivalent to pushing an image to Docker Hub.

Docker

docker push myrepo/myapp:1.0.0

CapMesh

capmesh tool push --file ./github-reader/manifest.yaml
capmesh agent push --file ./security-agent/manifest.yaml

Flags:

FlagDescriptionDefault
--file, -fPath to manifest.yamlrequired
--registry, -rCapMesh server URLhttp://localhost:8080
--overwriteReplace an existing draft (not allowed for approved versions)false
$ capmesh tool push --file ./github-reader/manifest.yaml --registry http://capmesh:8080 Connecting to registry: http://capmesh:8080 Authenticated as: platform-eng (org: acme-corp) Checking for conflicts... tools/github-reader:2.3.0 -- exists, different version, OK tools/github-reader:2.3.1 -- new version, no conflict Pushing tools/github-reader:2.3.1 Uploading manifest... done Computing digest... sha256:7a3f9c12d8e5b024f1a6c3d9e7f2b841a0c5d3e8f9b2a7c4d1e6f3b0a8c5d2e9 Indexing capabilities: repository.read/v1, repository.search/v1 Status: approved Pushed tools/github-reader:2.3.1 Capabilities now resolvable: repository.read/v1, repository.search/v1
Immutability: Once a version is pushed with status: approved, its content is locked to that digest. Attempting to push the same version number with different content returns an error. This is the same guarantee as Docker content-addressable layers.

capmesh tool pull  docker pull

Download a provider manifest from the registry to local disk -- useful for inspection, forking, or offline use.

Docker

docker pull myrepo/myapp:1.0.0

CapMesh

capmesh tool pull tools/github-reader:2.3.1
capmesh agent pull security/crewai-reviewer:3.1.0
$ capmesh tool pull tools/github-reader:2.3.1 --output ./local/ Pulling tools/github-reader:2.3.1 from http://capmesh:8080 Fetching manifest... done Verifying digest... sha256:7a3f9c12d8e5b024f1a6c3d9e7f2b841a0c5d3e8f9b2a7c4d1e6f3b0a8c5d2e9 OK Saved to ./local/github-reader-2.3.1/ manifest.yaml (1.4 KB) SKILL.md (not present for tool providers) Pull complete. Verify locally with: capmesh tool build --directory ./local/github-reader-2.3.1/

capmesh search  docker images / docker search

List all registered providers, optionally filtering by capability, type, or status.

Docker

docker images
docker search ubuntu

CapMesh

capmesh search
capmesh search --capability security.code.review
capmesh search --type agent
capmesh search --query "security scan"

Flags:

FlagDescription
--capabilityFilter by exact capability ID
--typeFilter by kind: tool | agent | skill
--queryNatural language keyword search
--statusFilter by governance status (approved | deprecated | revoked)
--namespaceFilter to one namespace
--jsonOutput as JSON array
$ capmesh search --capability security.code.review NAMESPACE NAME VERSION TYPE PROTOCOL STATUS DIGEST security crewai-security-reviewer 3.1.0 agent a2a approved sha256:3f9f55a4 security langgraph-security-reviewer 2.4.0 agent a2a approved sha256:9b2c71e8 security code-review-skill 1.2.0 skill skill approved sha256:4d7a8b3c security openai-reviewer 2.0.0 agent a2a deprecated sha256:1a2b3c4d 4 providers found for capability: security.code.review Resolution would select: security/crewai-security-reviewer:3.1.0 (highest approved semver)
$ capmesh search --query "notify the team" --json [ { "namespace": "comms", "name": "slack-notifier", "version": "4.0.2", "kind": "tool", "protocol": "mcp", "capabilities": ["notification.send", "notification.dm"], "status": "approved", "score": 0.92 }, { "namespace": "comms", "name": "teams-notifier", "version": "2.1.0", "kind": "tool", "protocol": "rest", "capabilities": ["notification.send"], "status": "approved", "score": 0.78 } ]

capmesh tool inspect  docker inspect

Print full details of a registered provider, including governance, interface, and all capabilities.

Docker

docker inspect myrepo/myapp:1.0.0

CapMesh

capmesh tool inspect tools/github-reader:2.3.1
capmesh agent inspect security/crewai-reviewer:3.1.0
$ capmesh agent inspect security/crewai-security-reviewer:3.1.0 Provider: security/crewai-security-reviewer:3.1.0 Kind: agent Protocol: a2a Digest: sha256:3f9f55a43b3cf6fa8d2b1c90e7f4a528b6c3d9e1f7a2b4c8d5e0f3a6b9c2d5e8 Pushed: 2026-09-20T11:44:02Z Pushed by: security-eng (org: acme-corp) Metadata api_version: capmesh.io/v1alpha1 owner: security-engineering labels: framework: crewai Governance status: approved visibility: public environment: [production, staging] Interface protocol: a2a endpoint: https://crewai-security.acme.com Provides - capability: security.code.review contract: v1 description: Review source code for security vulnerabilities, OWASP top 10, secrets Requires - capability: repository.read contract: v1 - capability: repository.search contract: v1 Resolution stats (last 7 days) Resolved: 847 times Last resolved: 2026-09-23T09:12:34Z

capmesh tag  docker tag

Create an alias pointing an existing provider to an additional name or version label.

Docker

docker tag myapp:1.0.0 myapp:latest
docker tag myapp:1.0.0 myrepo/myapp:stable

CapMesh

capmesh tag security/crewai-reviewer:3.1.0 \
    security/crewai-reviewer:stable

capmesh tag tools/github-reader:2.3.1 \
    tools/github-reader:latest
$ capmesh tag security/crewai-security-reviewer:3.1.0 security/crewai-security-reviewer:stable Tagged security/crewai-security-reviewer:3.1.0 as security/crewai-security-reviewer:stable Tag points to digest: sha256:3f9f55a43b3cf6fa...

capmesh login  docker login

Authenticate to a CapMesh registry. Credentials are stored in ~/.capmesh/config.json.

Docker

docker login registry.example.com

CapMesh

capmesh login http://capmesh.acme.com:8080
capmesh login --token $CAPMESH_TOKEN http://capmesh.acme.com:8080
$ capmesh login http://capmesh.acme.com:8080 Username: alice Password: ************** Login succeeded Registry: http://capmesh.acme.com:8080 Identity: alice (org: acme-corp, role: publisher) Token saved: ~/.capmesh/config.json

capmesh server start  docker run (for the registry)

Start the CapMesh registry server. Equivalent to running the registry container.

Docker (running the registry)

docker run -d \
  -p 5000:5000 \
  -v registry-data:/var/lib/registry \
  registry:2

CapMesh

capmesh server start --port 8080 \
  --db /data/capmesh.db \
  --host 0.0.0.0

Flags:

FlagDescriptionDefault
--portPort to listen on8080
--hostBind address127.0.0.1
--dbPath to SQLite database./capmesh.db
--log-leveldebug | info | warn | errorinfo
--corsAllowed CORS origins (comma-separated)disabled
$ capmesh server start --port 8080 --host 0.0.0.0 --db /data/capmesh.db CapMesh Registry Server v0.9.0 Listening: 0.0.0.0:8080 Database: /data/capmesh.db (new) Auth: disabled (set CAPMESH_AUTH_TOKEN to enable) [2026-09-23 09:00:01] INFO Server ready [2026-09-23 09:00:01] INFO GET /healthz -> 200 OK [2026-09-23 09:00:15] INFO POST /v1/providers/register -> 201 Created (tools/github-reader:2.3.1) [2026-09-23 09:00:22] INFO POST /v1/resolve -> 200 OK (security.code.review -> crewai-reviewer:3.1.0, 14ms)

CapMesh-Only Commands (no Docker equivalent)

capmesh resolve

Resolve a capability to its best provider right now, showing the full resolution trace.

capmesh resolve <capability> [--contract v1] [--caller identity] [--env production] [--constraint ">=2.0,<3.0"] [--kind agent|tool|skill] [--protocol mcp|a2a|rest|skill] [-k] [-p] [--trace] [--json]

Examples:

capmesh resolve "security scan"
capmesh resolve "security scan" --kind agent
capmesh resolve "read a repo" --protocol mcp
capmesh resolve security.code.review -k agent -p a2a
capmesh resolve security.code.review --trace --json

Flags:

FlagShortDescription
--kind-kFilter by provider kind: agent | tool | skill
--protocol-pFilter by protocol: mcp | a2a | rest | skill
--traceShow full 9-step resolution trace
--jsonOutput result as JSON
--contractRequire a specific contract version (default: v1)
--constraintSemver range filter, e.g. ">=2.0,<3.0"
--callerCaller identity for policy evaluation
--envCaller environment for policy evaluation
$ capmesh resolve security.code.review \ --contract v1 \ --caller ci-pipeline \ --env production \ --trace Resolving security.code.review/v1 Caller: ci-pipeline Environment: production Step 1 -- Find candidates (4 found) security/crewai-security-reviewer:3.1.0 security/langgraph-security-reviewer:2.4.0 security/code-review-skill:1.2.0 security/openai-reviewer:2.0.0 Step 2 -- Filter revoked [PASS] crewai-security-reviewer:3.1.0 (approved) [PASS] langgraph-security-reviewer:2.4.0 (approved) [PASS] code-review-skill:1.2.0 (approved) [SKIP] openai-reviewer:2.0.0 (deprecated) Step 3 -- Health check [PASS] all 3 candidates healthy (cached) Step 4 -- Contract match (v1) [PASS] all 3 match contract v1 Step 5 -- Policy (visibility: public, env: production) [PASS] crewai-security-reviewer:3.1.0 (env: [production, staging]) [PASS] langgraph-security-reviewer:2.4.0 (env: [production, staging]) [PASS] code-review-skill:1.2.0 (env: [production]) Step 6 -- Version constraint (none) [PASS] all 3 pass Step 7 -- Select best (highest semver) Selected: security/crewai-security-reviewer:3.1.0 Step 8 -- Build binding Protocol: a2a Endpoint: https://crewai-security.acme.com Step 9 -- Trace recorded Trace ID: res_8444e343826b Latency: 16 ms Result: provider: security/crewai-security-reviewer:3.1.0 protocol: a2a endpoint: https://crewai-security.acme.com

capmesh providers

List all providers for a specific capability, showing what would win resolution.

capmesh providers <capability> [--contract v1] [--verbose]
$ capmesh providers repository.read --contract v1 --verbose Providers for: repository.read/v1 RANK NAME VERSION PROTOCOL STATUS ENV 1 tools/github-reader 2.3.1 mcp approved [production, staging] 2 tools/gitlab-reader 2.0.0 mcp approved [production, staging, dev] 3 tools/bitbucket-reader 1.8.5 mcp approved [staging, dev] 4 tools/github-reader 2.2.0 mcp deprecated [production, staging] Resolution would select: tools/github-reader:2.3.1 (for env=production, unconstrained)

capmesh graph

Print the dependency graph for a provider -- what it requires and what provides those requirements.

capmesh graph <namespace/name:version>
$ capmesh graph security/crewai-security-reviewer:3.1.0 Dependency graph: security/crewai-security-reviewer:3.1.0 security/crewai-security-reviewer:3.1.0 [a2a agent] requires: repository.read/v1 --> tools/github-reader:2.3.1 [mcp tool] (would resolve to this) --> tools/gitlab-reader:2.0.0 [mcp tool] (also available) requires: repository.search/v1 --> tools/github-reader:2.3.1 [mcp tool] (would resolve to this, same server) Total transitive dependencies: 1 unique provider (github-reader:2.3.1) Full swap possible: yes (gitlab-reader covers both capabilities)

4 Build Providers -- Complete Working Examples

a) Build an MCP Tool MCP

An MCP tool wraps an existing MCP server. You do NOT rewrite the server. You write a manifest.yaml that tells CapMesh what capabilities this server provides and where to find it.

Scenario: The platform team has a github-mcp MCP server running. They want to register it so any agent can discover and use it.

# ./github-reader/manifest.yaml

metadata:
  api_version: capmesh.io/v1alpha1
  kind: tool
  name: github-reader
  namespace: tools
  owner: platform-engineering
  version: "2.3.1"

governance:
  status: approved
  visibility: public
  environment: [production, staging]

interface:
  protocol: mcp
  server: github-mcp                  # the MCP server name known to the MCP client
  tools:
    - read_file
    - search_code
    - list_files

provides:
  - capability: repository.read
    contract: v1
    description: Read files and directories from a GitHub repository

  - capability: repository.search
    contract: v1
    description: Search code within a GitHub repository

Build and push:

$ capmesh tool build --directory ./github-reader/ [OK] Required fields present [OK] Interface: protocol=mcp, server=github-mcp [OK] Capabilities: repository.read/v1, repository.search/v1 [OK] Semver: 2.3.1 Digest: sha256:7a3f9c12d8e5b024f1a6c3d9e7f2b841a0c5d3e8f9b2a7c4d1e6f3b0a8c5d2e9 Status: VALID $ capmesh tool push --file ./github-reader/manifest.yaml Pushing tools/github-reader:2.3.1... Indexed capabilities: repository.read/v1, repository.search/v1 Pushed tools/github-reader:2.3.1 Verify: capmesh tool inspect tools/github-reader:2.3.1

b) Build an A2A Agent A2A

An A2A agent exposes an HTTP endpoint that implements the A2A protocol. You declare the framework label so consumers know what kind of agent to expect, but CapMesh is framework-agnostic -- it just stores the label as metadata.

Scenario: The security team has a CrewAI-based security reviewer deployed at https://crewai-security.acme.com. They register it so any pipeline can discover it.

# ./security-agent/manifest.yaml

metadata:
  api_version: capmesh.io/v1alpha1
  kind: agent
  name: crewai-security-reviewer
  namespace: security
  owner: security-engineering
  version: "3.1.0"
  labels:
    framework: crewai                # metadata only -- not enforced by CapMesh

governance:
  status: approved
  visibility: public
  environment: [production, staging]

interface:
  protocol: a2a
  endpoint: https://crewai-security.acme.com   # where the agent is ACTUALLY running

provides:
  - capability: security.code.review
    contract: v1
    description: >
      Review source code for security vulnerabilities (OWASP Top 10,
      secrets exposure, dependency risks). Returns structured findings.

requires:
  - capability: repository.read
    contract: v1
  - capability: repository.search
    contract: v1
$ capmesh agent build --directory ./security-agent/ [OK] Kind: agent [OK] Protocol: a2a [OK] Endpoint: https://crewai-security.acme.com (valid URL) [OK] Framework label: crewai [OK] Provides: security.code.review/v1 [OK] Requires: repository.read/v1, repository.search/v1 [OK] Semver: 3.1.0 Digest: sha256:3f9f55a43b3cf6fa8d2b1c90e7f4a528b6c3d9e1f7a2b4c8d5e0f3a6b9c2d5e8 Status: VALID $ capmesh agent push --file ./security-agent/manifest.yaml Pushing security/crewai-security-reviewer:3.1.0... Indexed capabilities: security.code.review/v1 Framework label stored: crewai Pushed security/crewai-security-reviewer:3.1.0 Agents needing security.code.review will now discover this provider.

c) Build a Skill SKILL

A Skill is a reusable procedure defined in a SKILL.md file. It contains human-readable (and LLM-readable) instructions. CapMesh resolves its tool dependencies separately at bind time, so the same skill works with GitHub, GitLab, or any other tool that satisfies the required capabilities.

Scenario: The engineering team writes a standard PR review procedure as a skill.

# ./pr-review-skill/manifest.yaml

metadata:
  api_version: capmesh.io/v1alpha1
  kind: skill
  name: pr-review
  namespace: engineering
  owner: platform-engineering
  version: "1.0.0"

governance:
  status: approved
  visibility: public
  environment: [production, staging, dev]

interface:
  protocol: skill
  skill_file: SKILL.md              # path relative to this manifest.yaml

provides:
  - capability: pr.review
    contract: v1
    description: >
      Perform a full pull request review: read changed files,
      run a security scan, check coding standards, summarize findings.

requires:
  - capability: repository.read
    contract: v1
  - capability: security.code.review
    contract: v1
  - capability: notification.send
    contract: v1
# ./pr-review-skill/SKILL.md

# PR Review Skill

## Purpose
Perform a structured pull request review using the tools provided by the caller's environment.

## Steps

1. **Read the diff**
   Use the `repository.read` tool to fetch the list of changed files in the PR.
   For each file, read its content and the diff.

2. **Security scan**
   Pass the changed file contents to the `security.code.review` tool.
   Collect findings: severity (critical/high/medium/low), file, line, description.

3. **Summarize**
   Produce a JSON report:
   ```json
   {
     "pr":       "<PR identifier>",
     "files":    "<count>",
     "findings": [ {"severity": "...", "file": "...", "line": "...", "desc": "..."} ],
     "verdict":  "approve | request_changes | needs_discussion"
   }
   ```

4. **Notify**
   Use the `notification.send` tool to post the summary to the PR thread.

## Notes
- Do NOT hardcode which tool provides repository.read or security.code.review.
  Use whatever was bound by CapMesh at resolve time.
- If security.code.review returns 0 critical findings, verdict = approve.
- If any critical finding, verdict = request_changes.
$ capmesh skill build --directory ./pr-review-skill/ [OK] Kind: skill [OK] SKILL.md found and readable (1.2 KB) [OK] Provides: pr.review/v1 [OK] Requires: repository.read/v1, security.code.review/v1, notification.send/v1 [OK] All required capabilities have registered providers [OK] Semver: 1.0.0 Digest: sha256:b4c2d9e7f1a3b8c5d0e6f2a9b3c7d1e8f4a0b5c9d2e7f3a1b6c4d8e2f7a5b0c3 Status: VALID $ capmesh skill push --file ./pr-review-skill/manifest.yaml Pushing engineering/pr-review:1.0.0... Indexed capabilities: pr.review/v1 SKILL.md stored (1.2 KB) Requires: repository.read/v1, security.code.review/v1, notification.send/v1 Pushed engineering/pr-review:1.0.0 At bind time, CapMesh will resolve all 3 required capabilities independently.

d) Build a REST Tool REST

A REST tool is any HTTP API that a consumer can call directly. CapMesh registers the base URL and any auth requirements so consumers can discover and use it without knowing the exact address.

Scenario: The security team uses SonarCloud for static analysis. They register it as a REST tool.

# ./sonarcloud-scanner/manifest.yaml

metadata:
  api_version: capmesh.io/v1alpha1
  kind: tool
  name: sonarcloud-scanner
  namespace: security
  owner: security-engineering
  version: "1.4.0"

governance:
  status: approved
  visibility: organization
  environment: [production, staging]

interface:
  protocol: rest
  endpoint: https://sonarcloud.io/api          # the actual REST API base URL
  auth:
    type: bearer
    env_var: SONARCLOUD_TOKEN                  # consumer must have this env var set

provides:
  - capability: security.static.analysis
    contract: v1
    description: Static code analysis via SonarCloud. POST /measures/component.

  - capability: security.vulnerability.report
    contract: v1
    description: Fetch vulnerability report for a component.
$ capmesh tool build --directory ./sonarcloud-scanner/ [OK] Kind: tool [OK] Protocol: rest [OK] Endpoint: https://sonarcloud.io/api (valid URL) [OK] Auth type: bearer (env_var: SONARCLOUD_TOKEN) [OK] Provides: security.static.analysis/v1, security.vulnerability.report/v1 [OK] Visibility: organization [OK] Semver: 1.4.0 Digest: sha256:c9d2e7f3a1b6c4d8e2f7a5b0c3d9e6f1a4b8c2d5e9f0a3b7c1d4e8f2a6b9c3d7 Status: VALID $ capmesh tool push --file ./sonarcloud-scanner/manifest.yaml Pushing security/sonarcloud-scanner:1.4.0... Visibility: organization (acme-corp members only) Indexed capabilities: security.static.analysis/v1, security.vulnerability.report/v1 Pushed security/sonarcloud-scanner:1.4.0

5 Runtime API Endpoints -- What Providers Expose

CapMesh is a registry, not a proxy. When a consumer resolves a capability, it gets back a binding -- connection information for the provider. The consumer then calls the provider directly. CapMesh is never in the data path.

The provider team runs the actual service. They just write a manifest.yaml to register it. CapMesh does not host it, proxy it, or relay traffic to it -- it simply tells consumers where to find it. This is exactly how DNS works.

What each provider type exposes

A2A Agent: An HTTPS endpoint that the agent team deploys and operates. Implements the A2A protocol (POST task, GET status, streaming). CapMesh stores this URL and returns it in the binding. The consumer calls this URL directly using an A2A client.

Example: https://security-agent.acme.com -- the security team's server.

MCP Tool: An MCP server registered under a name in the MCP client configuration. CapMesh stores the server name. The consumer uses this server name when calling its MCP client library.

Example: github-mcp -- the platform team's MCP server, known to the MCP client.

REST Tool: A publicly reachable HTTP/HTTPS API base URL. CapMesh stores the URL and auth requirements. The consumer makes direct HTTP calls to this URL.

Example: https://api.example.com/v1/scan -- the vendor's API endpoint.

Skill: A SKILL.md file stored in the CapMesh registry. CapMesh returns the instructions AND resolves all tool dependencies separately. The consumer executes the skill using the resolved tool bindings.

Example: SKILL.md path in the registry -- the team's procedure document.

What a binding looks like for each type

MCP Tool binding:

{
  "provider":  "tools/github-reader:2.3.1",
  "protocol":  "mcp",
  "connection": {
    "server":    "github-mcp",
    "tool_name": "read_file"
  },
  "trace_id":  "res_1a2b3c4d5e6f"
}

A2A Agent binding:

{
  "provider":  "security/crewai-security-reviewer:3.1.0",
  "protocol":  "a2a",
  "connection": {
    "endpoint":  "https://crewai-security.acme.com",
    "framework": "crewai"
  },
  "trace_id":  "res_8444e343826b"
}

REST Tool binding:

{
  "provider":  "security/sonarcloud-scanner:1.4.0",
  "protocol":  "rest",
  "connection": {
    "endpoint":  "https://sonarcloud.io/api",
    "auth": {
      "type":    "bearer",
      "env_var": "SONARCLOUD_TOKEN"
    }
  },
  "trace_id":  "res_9c8b7a6d5e4f"
}

Skill binding (dual binding -- instructions + tool deps resolved separately):

{
  "provider":  "engineering/pr-review:1.0.0",
  "protocol":  "skill",
  "connection": {
    "instructions": "# PR Review Skill\n\n## Steps\n...",
    "tool_bindings": [
      {
        "capability": "repository.read",
        "provider":   "tools/github-reader:2.3.1",
        "protocol":   "mcp",
        "connection": { "server": "github-mcp", "tool_name": "read_file" }
      },
      {
        "capability": "security.code.review",
        "provider":   "security/crewai-security-reviewer:3.1.0",
        "protocol":   "a2a",
        "connection": { "endpoint": "https://crewai-security.acme.com" }
      },
      {
        "capability": "notification.send",
        "provider":   "comms/slack-notifier:4.0.2",
        "protocol":   "mcp",
        "connection": { "server": "slack-mcp", "tool_name": "post_message" }
      }
    ]
  },
  "trace_id": "res_3d2c1b0a9e8f"
}

6 Use Providers -- Resolve and Call

a) Python SDK -- Resolve and Call

"""
Example: A CI pipeline that resolves a security scanner and runs it.
The pipeline does NOT know which scanner will be returned.
"""

import capmesh

# One-line setup
mesh = capmesh.connect()

# --- Resolve a capability (exact ID) ---
result = mesh.resolve("security.code.review")

print(f"Provider:  {result.provider}")       # security/crewai-security-reviewer:3.1.0
print(f"Protocol:  {result.protocol}")       # a2a
print(f"Trace ID:  {result.trace_id}")       # res_8444e343826b
print(f"Endpoint:  {result.binding.connection['endpoint']}")
# https://crewai-security.acme.com

# --- Resolve a capability (natural language) ---
binding = mesh.need("read files from a code repository")
print(f"Provider:  {binding.provider}")      # tools/github-reader:2.3.1
print(f"Protocol:  {binding.protocol}")      # mcp
print(f"Server:    {binding.connection['server']}")  # github-mcp

# --- Filter by kind and/or protocol ---
agent = mesh.need("security scan", kind="agent")
tool  = mesh.need("read repo", kind="tool", protocol="mcp")
print(f"Agent:  {agent.provider}")           # security/crewai-security-reviewer:3.1.0
print(f"Tool:   {tool.provider}")            # tools/github-reader:2.3.1

# --- Exact ID with filter ---
result = mesh.resolve("security.code.review", kind="agent")

# --- List all providers for a capability ---
providers = mesh.providers("security.code.review")
for p in providers:
    print(f"  {p.provider} ({p.protocol})")
Provider: security/crewai-security-reviewer:3.1.0 Protocol: a2a Trace ID: res_8444e343826b Endpoint: https://crewai-security.acme.com Provider: tools/github-reader:2.3.1 Protocol: mcp Server: github-mcp Agent: security/crewai-security-reviewer:3.1.0 Tool: tools/github-reader:2.3.1

b) Raw HTTP API -- Resolve and Return Binding

No SDK required. Any HTTP client works.

POST http://capmesh:8080/v1/resolve
Content-Type: application/json

{
  "capability":  "security.code.review",
  "contract":    "v1",
  "caller": {
    "identity":    "ci-pipeline",
    "environment": "production",
    "namespace":   "eng"
  }
}

Full response:

{
  "status":    "resolved",
  "trace_id":  "res_8444e343826b",
  "capability": "security.code.review",
  "contract":   "v1",
  "provider":   "security/crewai-security-reviewer:3.1.0",
  "protocol":   "a2a",
  "binding": {
    "connection": {
      "endpoint":  "https://crewai-security.acme.com",
      "framework": "crewai"
    }
  },
  "resolution_ms": 14,
  "selected_from": 3,
  "candidates": [
    { "provider": "security/crewai-security-reviewer:3.1.0",    "passed": true,  "reason": "selected (highest semver)" },
    { "provider": "security/langgraph-security-reviewer:2.4.0", "passed": true,  "reason": "available but lower semver" },
    { "provider": "security/code-review-skill:1.2.0",           "passed": true,  "reason": "available but lower semver" }
  ]
}

c) Using the Binding to Call the Actual Service

Once you have the binding, you call the provider directly. CapMesh is no longer involved.

import httpx
import json
from mcp import MCPClient
from a2a import A2AClient

def resolve_and_call(capability: str, payload: dict) -> dict:
    """
    Resolve a capability and call the provider.
    Works regardless of which provider is returned.
    """
    # Step 1: resolve
    resp = httpx.post("http://capmesh:8080/v1/resolve", json={
        "capability": capability,
        "contract":   "v1",
        "caller": {"identity": "my-agent", "environment": "production"}
    })
    resp.raise_for_status()
    result = resp.json()

    protocol   = result["protocol"]
    connection = result["binding"]["connection"]

    # Step 2: call the provider directly
    if protocol == "a2a":
        client = A2AClient(base_url=connection["endpoint"])
        return client.submit_task(payload)

    elif protocol == "mcp":
        client = MCPClient()
        return client.call_tool(
            server=connection["server"],
            tool=connection.get("tool_name", "default"),
            arguments=payload,
        )

    elif protocol == "rest":
        token = os.environ.get(connection["auth"]["env_var"])
        return httpx.post(
            connection["endpoint"],
            json=payload,
            headers={"Authorization": f"Bearer {token}"},
        ).json()

    elif protocol == "skill":
        instructions = connection["instructions"]
        tool_bindings = connection["tool_bindings"]
        # Execute the skill instructions using the bound tools
        return execute_skill(instructions, tool_bindings, payload)

    else:
        raise ValueError(f"Unknown protocol: {protocol}")


# Use it -- no hardcoded providers anywhere
findings = resolve_and_call("security.code.review", {
    "repo":   "acme-corp/backend-api",
    "pr":     "1247",
    "branch": "feature/auth-refactor"
})
# What the A2A agent at https://crewai-security.acme.com returned: { "findings": [ { "severity": "high", "file": "src/auth/token.py", "line": 84, "rule": "SEC-JWT-001", "desc": "JWT token signed with HS256 using weak secret (len < 32)" }, { "severity": "medium", "file": "src/auth/session.py", "line": 122, "rule": "SEC-SESS-003", "desc": "Session cookie missing HttpOnly and Secure flags" } ], "verdict": "request_changes", "scanned_files": 14, "duration_ms": 3240 }

7 Framework Integration -- Discover and Use Capabilities

Every framework follows the same 3-step pattern. The only thing that changes is how you wrap the CapMesh binding into your framework's tool type.

The Pattern: 1. mesh.need("what I need") -- discover the capability
2. Get back: protocol, endpoint/server, connection info
3. Wrap into your framework's tool type and use it

Step 1: Discover -- How agents find capabilities

Before using a capability, agents need to find it. Three ways:

import capmesh
mesh = capmesh.connect()

# Natural language -- agent describes what it needs
binding = mesh.need("read code from a repository")
binding = mesh.need("scan for security vulnerabilities")
binding = mesh.need("notify the team on slack")

# With kind/protocol filters
agent   = mesh.need("security scan", kind="agent")
tool    = mesh.need("read a repo", kind="tool", protocol="mcp")

# Exact ID -- when you know the capability name
binding = mesh.resolve("security.code.review")
binding = mesh.resolve("security.code.review", kind="agent")

# Explore -- see what's available (ranked by relevance)
results = mesh.discover("security")
# [
#   {capability: "security.code.review", score: 0.9, reason: "substring match"},
#   {capability: "security.scan",        score: 0.9, reason: "substring match"},
# ]

# List providers for a capability
providers = mesh.providers("security.code.review")

# Register a manifest
mesh.register("manifest.yaml")

# Search the registry
results = mesh.search("security")
# mesh.need("read code from a repository") returns: provider: repository/gitlab-reader:2.0.0 protocol: mcp connection: {"server": "gitlab-mcp", "tool_name": "read_file"} trace_id: res_8444e343826b # mesh.need("scan for security vulnerabilities") returns: provider: security/crewai-reviewer:3.1.0 protocol: a2a connection: {"endpoint": "https://crewai-security.example.com"} trace_id: res_b825e80e75d0 # mesh.need("security scan", kind="agent") returns: provider: security/crewai-reviewer:3.1.0 (agents only) # mesh.need("read a repo", kind="tool", protocol="mcp") returns: provider: tools/github-reader:2.3.1 (MCP tools only)

Step 2: What comes back -- the Binding

Every resolution returns a binding with protocol-specific connection info:

ProtocolWhat you get backHow you call it
mcp{"server": "github-mcp", "tool_name": "read_file"}MCP client calls the server
a2a{"endpoint": "https://agent.example.com"}A2A client calls the endpoint
rest{"endpoint": "https://api.example.com", "auth_type": "bearer"}HTTP POST to the endpoint
skill{"instructions": "SKILL.md", "tool_bindings": [...]}Load instructions + use resolved tools

Step 3: Use it -- Framework Examples

CrewAI

# pip install crewai capmesh
from crewai import Agent, Task, Crew
import capmesh

# Connect to CapMesh once
mesh = capmesh.connect()

# Discover capabilities (optionally filter by kind/protocol)
repo = mesh.need("read a repository", kind="tool", protocol="mcp")
scan = mesh.need("security scan", kind="agent")

# Build CrewAI tools from CapMesh bindings
def make_crewai_tool(binding):
    if binding.binding.protocol == "mcp":
        # from crewai_tools import MCPTool
        # return MCPTool(server=binding.binding.connection["server"])
        return f"MCPTool(server='{binding.binding.connection['server']}')"
    elif binding.binding.protocol == "a2a":
        # return A2ATool(endpoint=binding.binding.connection["endpoint"])
        return f"A2ATool(endpoint='{binding.binding.connection['endpoint']}')"

repo_tool = make_crewai_tool(repo)   # MCPTool resolved dynamically
scan_tool = make_crewai_tool(scan)   # A2ATool resolved dynamically

# Create CrewAI agent with dynamic tools
# agent = Agent(
#     role="Security Reviewer",
#     goal="Find vulnerabilities in code",
#     tools=[repo_tool, scan_tool],    # DYNAMIC -- not hardcoded
# )
# task = Task(description="Review PR #42", agent=agent)
# crew = Crew(agents=[agent], tasks=[task])
# result = crew.kickoff()
# What CapMesh resolved for CrewAI: repo_tool = MCPTool(server='gitlab-mcp') # was GitHub, now GitLab -- no code change scan_tool = A2ATool(endpoint='https://crewai-security.example.com') # CrewAI agent runs with these tools. If you register a new scanner # tomorrow, the agent gets it automatically on next run.

LangGraph / LangChain

# pip install langgraph langchain capmesh
from langchain_core.tools import tool
from langgraph.graph import StateGraph
import capmesh

mesh = capmesh.connect()

# Resolve tools at graph build time (filter by kind/protocol as needed)
repo_binding = mesh.need("read repository code", kind="tool", protocol="mcp")
scan_binding = mesh.need("security review", kind="agent")

# Create LangChain tools from bindings
@tool
def read_repo(repo: str) -> dict:
    """Read repository files. Provider resolved by CapMesh."""
    conn = repo_binding.binding.connection
    if repo_binding.binding.protocol == "mcp":
        return mcp_client.call(conn["server"], {"repo": repo})
    return httpx.get(conn["endpoint"], params={"repo": repo}).json()

@tool
def security_scan(files: list) -> dict:
    """Run security scan. Provider resolved by CapMesh."""
    conn = scan_binding.binding.connection
    return a2a_client.submit_task(conn["endpoint"], {"files": files})

# Build LangGraph
# graph = StateGraph(ReviewState)
# graph.add_node("read", read_repo)
# graph.add_node("scan", security_scan)
# graph.add_edge("read", "scan")
# app = graph.compile()
# result = app.invoke({"repo": "myorg/webapp"})
# CapMesh resolved for LangGraph: read_repo -> repository/gitlab-reader:2.0.0 via MCP (server: gitlab-mcp) scan -> security/crewai-reviewer:3.1.0 via A2A (endpoint: https://crewai-security.example.com) # The graph definition never changes. Only the bindings change. # Register gitlab-reader:3.0.0 tomorrow -- graph auto-uses it on next build.

AWS Strands

# pip install strands-agents capmesh
import capmesh

mesh = capmesh.connect()

# Discover what's available
results = mesh.discover("repository")
print(f"Found {len(results)} capabilities matching 'repository':")
for r in results:
    print(f"  [{r.score:.1f}] {r.capability} -- {r.reason}")

# Resolve the best one (filter to MCP tools only)
repo = mesh.need("read repository", kind="tool", protocol="mcp")

# Build Strands agent
# from strands import Agent
# from strands.tools import MCPTool, HTTPTool
#
# if repo.binding.protocol == "mcp":
#     tool = MCPTool(repo.binding.connection["server"])
# elif repo.binding.protocol == "rest":
#     tool = HTTPTool(repo.binding.connection["endpoint"])
#
# agent = Agent(tools=[tool])
# result = agent("Read the auth module from myorg/webapp")
# Discovery results: Found 2 capabilities matching 'repository': [0.9] repository.read -- query is substring of 'repository.read' [0.9] repository.search -- query is substring of 'repository.search' # Resolution: repo -> repository/gitlab-reader:2.0.0 via MCP Connection: {"server": "gitlab-mcp", "tool_name": "read_file"}

Microsoft AutoGen

# pip install autogen-agentchat capmesh
import capmesh

mesh = capmesh.connect()

# Resolve and create tool functions
def capmesh_tool(capability: str, kind: str = None, protocol: str = None):
    result = mesh.need(capability, kind=kind, protocol=protocol)
    conn = result.binding.connection

    def tool_fn(**kwargs):
        if result.binding.protocol == "a2a":
            return a2a_client.call(conn["endpoint"], kwargs)
        elif result.binding.protocol == "mcp":
            return mcp_client.call(conn["server"], kwargs)
        elif result.binding.protocol == "rest":
            return httpx.post(conn["endpoint"], json=kwargs).json()

    tool_fn.__name__ = capability.replace(".", "_")
    return tool_fn

# Register tools with AutoGen (filter by kind/protocol to be explicit)
read_repo = capmesh_tool("repository.read", kind="tool", protocol="mcp")
scan_code = capmesh_tool("security.code.review", kind="agent")

# from autogen import AssistantAgent, UserProxyAgent
# assistant = AssistantAgent("reviewer", llm_config={...})
# assistant.register_function({"read_repo": read_repo, "scan_code": scan_code})
# user_proxy = UserProxyAgent("user")
# user_proxy.initiate_chat(assistant, message="Review PR #42")

Google Agent Development Kit (ADK)

# pip install google-adk capmesh
import capmesh

mesh = capmesh.connect()

# Resolve multiple capabilities at once (with kind/protocol filters)
bindings = {
    "read a repo":       mesh.need("read a repo",       kind="tool", protocol="mcp"),
    "security scan":     mesh.need("security scan",     kind="agent"),
    "send notification": mesh.need("send notification", kind="tool"),
}

# Convert to Google ADK tools
# from google.adk import Agent
# from google.adk.tools import FunctionTool
#
# adk_tools = []
# for cap, binding in bindings.items():
#     conn = binding.binding.connection
#     if binding.binding.protocol == "mcp":
#         adk_tools.append(FunctionTool(name=cap,
#             fn=lambda **kw: mcp_client.call(conn["server"], kw)))
#     elif binding.binding.protocol == "a2a":
#         adk_tools.append(FunctionTool(name=cap,
#             fn=lambda **kw: a2a_client.call(conn["endpoint"], kw)))
#
# agent = Agent(model="gemini-2.0-flash", tools=adk_tools)
# result = agent.run("Review this repository for security issues")
# CapMesh resolved for Google ADK: read a repo -> repository/gitlab-reader:2.0.0 (mcp, server: gitlab-mcp) security scan -> security/crewai-reviewer:3.1.0 (a2a, endpoint: https://crewai-security.example.com) send notification -> notifications/slack-notifier:1.0.0 (rest, endpoint: https://slack.example.com/api) # Not locked to Google's tool ecosystem. Any MCP/A2A/REST provider works.

OpenAI Agents SDK

# pip install openai capmesh
import capmesh

mesh = capmesh.connect()

# Generate OpenAI function schemas from CapMesh bindings
def make_openai_tool(capability: str, kind: str = None, protocol: str = None):
    result = mesh.need(capability, kind=kind, protocol=protocol)
    return {
        "type": "function",
        "function": {
            "name": capability.replace(".", "_").replace(" ", "_"),
            "description": f"Resolved: {result.provider_name}:{result.provider_version} via {result.binding.protocol}",
            "parameters": {"type": "object", "properties": {
                "input": {"type": "string", "description": "Input data"}
            }},
        },
        "_capmesh_binding": result.binding,  # keep binding for dispatch
    }

tools = [
    make_openai_tool("repository.read",      kind="tool", protocol="mcp"),
    make_openai_tool("security.code.review", kind="agent"),
]

# from openai import OpenAI
# client = OpenAI()
# response = client.chat.completions.create(
#     model="gpt-4",
#     messages=[{"role": "user", "content": "Review PR #42"}],
#     tools=tools,
# )
# # Dispatch tool calls to CapMesh-resolved providers
# for call in response.choices[0].message.tool_calls:
#     binding = tools[call.function.name]._capmesh_binding
#     result = dispatch(binding, call.function.arguments)

Microsoft Semantic Kernel

# pip install semantic-kernel capmesh
import capmesh

mesh = capmesh.connect()

# Resolve and create SK kernel functions (filter by kind/protocol)
repo = mesh.need("read a repository", kind="tool", protocol="mcp")
scan = mesh.need("security scan", kind="agent")

# import semantic_kernel as sk
# from semantic_kernel.functions import kernel_function
#
# kernel = sk.Kernel()
#
# @kernel_function(name="read_repo")
# def read_repo(repo_name: str) -> str:
#     conn = repo.binding.connection
#     return mcp_client.call(conn["server"], {"repo": repo_name})
#
# @kernel_function(name="security_scan")
# def security_scan(code: str) -> str:
#     conn = scan.binding.connection
#     return a2a_client.call(conn["endpoint"], {"code": code})
#
# kernel.add_function("tools", read_repo)
# kernel.add_function("tools", security_scan)
# result = await kernel.invoke("tools", "read_repo", repo_name="myorg/app")

Any Language -- Raw HTTP (Python, JavaScript, Go, Java, curl)

No SDK required. Just one HTTP call.

# Python
import httpx
resp = httpx.post("http://capmesh:8080/v1/resolve", json={
    "capability": "security.code.review", "contract": "v1",
    "caller": {"identity": "my-app"}
})
binding = resp.json()
# Use binding["binding"]["endpoint"] to call the provider
# curl
curl -X POST http://capmesh:8080/v1/resolve \
  -H "Content-Type: application/json" \
  -d '{"capability":"security.code.review","contract":"v1","caller":{"identity":"my-app"}}'
// JavaScript
const resp = await fetch("http://capmesh:8080/v1/resolve", {
  method: "POST",
  headers: {"Content-Type": "application/json"},
  body: JSON.stringify({capability: "security.code.review", contract: "v1", caller: {identity: "my-app"}})
});
const binding = await resp.json();
// Use binding.binding.endpoint
// Go
body := `{"capability":"security.code.review","contract":"v1","caller":{"identity":"my-app"}}`
resp, _ := http.Post("http://capmesh:8080/v1/resolve", "application/json", strings.NewReader(body))

Caching -- Repeated Resolutions are Fast

CapMesh caches resolution results with a 30-second TTL. Cache auto-invalidates when providers are registered, deleted, or deprecated.

import capmesh
mesh = capmesh.connect()

# First call: hits SQLite (~16ms)
mesh.need("security scan")

# Second call: cache hit (~0ms)
mesh.need("security scan")

# Register a new provider: cache auto-invalidates
mesh.register("new_scanner_manifest.yaml")

# Next call: fresh resolution (~16ms), picks new provider
mesh.need("security scan")

# Check cache performance
print(mesh.cache_stats)
# {"hits": 142, "misses": 18, "size": 12}
Same pattern, every framework: Discover with mesh.need(), get back a binding (protocol + connection info), wrap it into your framework's tool type. Optionally add kind= or protocol= to narrow results. The framework-specific code is 3-5 lines. Everything else -- discovery, versioning, policy, audit, caching -- is handled by CapMesh.

8 Backward Compatibility -- Zero Code Changes to Providers

CapMesh requires NO changes to existing providers. If you have an agent running today, just write a manifest.yaml pointing at it. If you have an MCP server, just write a manifest.yaml with its server name. The provider never knows CapMesh exists.

Existing A2A Agent -- No Changes

You have a LangGraph agent deployed at https://my-agent.acme.com. It has been running for months. You want to make it discoverable through CapMesh.

What you do: Write one manifest.yaml. Push it. Done.

# manifest.yaml -- the ONLY thing you need
metadata:
  api_version: capmesh.io/v1alpha1
  kind: agent
  name: my-existing-langgraph-agent
  namespace: ml
  owner: ml-team
  version: "1.0.0"
  labels:
    framework: langgraph              # metadata only

governance:
  status: approved
  visibility: public
  environment: [production]

interface:
  protocol: a2a
  endpoint: https://my-agent.acme.com   # already running, no changes needed

provides:
  - capability: data.analysis
    contract: v1
    description: Analyze datasets and produce statistical summaries
$ capmesh agent push --file ./manifest.yaml Pushed ml/my-existing-langgraph-agent:1.0.0 endpoint: https://my-agent.acme.com The agent is now discoverable. No changes were made to the agent itself. No SDK installed on the agent. No agent code touched. Consumers resolving data.analysis/v1 will be directed to https://my-agent.acme.com.

Existing MCP Server -- No Changes

You have an MCP server named my-github-mcp in your MCP client config. It has been running for months. You want to make it discoverable through CapMesh.

# manifest.yaml
metadata:
  api_version: capmesh.io/v1alpha1
  kind: tool
  name: my-github-mcp-tool
  namespace: tools
  owner: platform-eng
  version: "3.0.0"

governance:
  status: approved
  visibility: public
  environment: [production, staging]

interface:
  protocol: mcp
  server: my-github-mcp             # the existing server name -- no changes needed
  tools:
    - read_file
    - list_files

provides:
  - capability: repository.read
    contract: v1
    description: Read files from a GitHub repository via MCP
$ capmesh tool push --file ./manifest.yaml Pushed tools/my-github-mcp-tool:3.0.0 server: my-github-mcp The MCP server is now discoverable via CapMesh. No changes to the MCP server. No SDK. No code modifications. Consumers resolving repository.read/v1 may receive server=my-github-mcp.

No SDK Required on the Provider Side

ScenarioWhat provider team doesWhat changes in provider code
Register existing A2A agentWrite manifest.yaml, run capmesh agent pushNothing
Register existing MCP serverWrite manifest.yaml, run capmesh tool pushNothing
Register existing REST APIWrite manifest.yaml, run capmesh tool pushNothing
Write a new skillWrite manifest.yaml + SKILL.md, run capmesh skill pushNothing (skill is docs, not code)
Upgrade to a new versionBump version in manifest.yaml, push againNothing (if the endpoint didn't change)

9 In Action -- Three Scenarios

a) PR Review Pipeline

A CI pipeline resolves 4 capabilities, chains results, and produces a final report. The pipeline never hardcodes which tools to use.

"""pr_review_pipeline.py"""
import httpx, json

CAPMESH = "http://capmesh:8080"
PR = {"repo": "acme-corp/backend-api", "pr": "1247", "branch": "feature/auth-refactor"}

def resolve(capability):
    r = httpx.post(f"{CAPMESH}/v1/resolve", json={
        "capability": capability, "contract": "v1",
        "caller": {"identity": "ci-pipeline", "environment": "production"}
    })
    r.raise_for_status()
    return r.json()

# Step 1: Find the repo reader
repo_binding = resolve("repository.read")

# Step 2: Find a security reviewer
sec_binding = resolve("security.code.review")

# Step 3: Find a code quality checker
quality_binding = resolve("code.quality.check")

# Step 4: Find a notification channel
notify_binding = resolve("notification.send")

print(json.dumps({
    "repository.read":    repo_binding["provider"],
    "security.review":    sec_binding["provider"],
    "quality.check":      quality_binding["provider"],
    "notification.send":  notify_binding["provider"],
}, indent=2))

# Now call each provider using its binding...
# (abbreviated: see section 6c for full call logic)
Resolution results: { "repository.read": "tools/github-reader:2.3.1", "security.review": "security/crewai-security-reviewer:3.1.0", "quality.check": "quality/sonarcloud-scanner:1.4.0", "notification.send": "comms/slack-notifier:4.0.2" } --- Step 1: Read diff (github-mcp / read_file) --- Changed files: 14 Total lines changed: +312 / -87 --- Step 2: Security review (https://crewai-security.acme.com) --- Findings: 2 HIGH src/auth/token.py:84 JWT weak secret (SEC-JWT-001) MEDIUM src/auth/session.py:122 Cookie missing HttpOnly flag (SEC-SESS-003) --- Step 3: Quality check (https://sonarcloud.io/api) --- Code smells: 3 Duplications: 1.2% Coverage delta: -0.4% Quality gate: PASSED --- Step 4: Notify (slack-mcp / post_message) --- Posted to #pr-reviews Message: "PR #1247 -- 2 security findings (1 HIGH). Quality gate PASSED." Slack message ID: C04X8YNZP1T.1727081234.000400 --- Final Report --- { "pr": "1247", "repo": "acme-corp/backend-api", "status": "request_changes", "security": {"findings": 2, "highest": "high"}, "quality_gate": "passed", "notified": true, "trace_ids": [ "res_1a2b3c4d5e6f", "res_8444e343826b", "res_9c8b7a6d5e4f", "res_2d3e4f5a6b7c" ] }

b) Provider Swap -- Zero Code Changes

The security team decides to replace Snyk with Semgrep. The pipeline code does not change. The swap takes 30 seconds.

Before:

$ capmesh providers security.static.analysis --contract v1 RANK NAME VERSION STATUS SELECTED 1 security/snyk-scanner 2.1.0 approved YES (highest semver) 2 security/semgrep-scanner 1.8.0 approved no Pipeline resolves -> security/snyk-scanner:2.1.0

The security team pushes a new version of Semgrep:

$ capmesh tool push --file ./semgrep-scanner/manifest.yaml
# manifest.yaml has version: "3.0.0" -- higher than snyk:2.1.0
$ capmesh tool push --file ./semgrep-scanner/manifest.yaml Pushed security/semgrep-scanner:3.0.0 Indexed: security.static.analysis/v1 $ capmesh providers security.static.analysis --contract v1 RANK NAME VERSION STATUS SELECTED 1 security/semgrep-scanner 3.0.0 approved YES (highest semver) 2 security/snyk-scanner 2.1.0 approved no 3 security/semgrep-scanner 1.8.0 approved no

After: All pipelines that resolve security.static.analysis/v1 now get Semgrep 3.0.0 automatically. No pipeline code changed.

$ capmesh resolve security.static.analysis --contract v1 --caller ci-pipeline --env production Selected: security/semgrep-scanner:3.0.0 Protocol: rest Endpoint: https://semgrep.dev/api/v1/scan Trace: res_4e5f6a7b8c9d (Previously would have returned snyk-scanner:2.1.0)

If the team needs to roll back, they deprecate Semgrep 3.0.0:

capmesh tool deprecate security/semgrep-scanner:3.0.0
$ capmesh tool deprecate security/semgrep-scanner:3.0.0 Deprecated security/semgrep-scanner:3.0.0 Fallback: security/snyk-scanner:2.1.0 will be selected on next resolution. Existing trace records preserved for audit.

c) Dynamic Discovery -- Register at Runtime, Immediately Available

A new team just deployed a specialized code reviewer for Python at https://python-reviewer.acme.com. They register it at runtime. No restarts needed anywhere.

import httpx, json

# Register via HTTP API -- no CLI needed
manifest = {
    "metadata": {
        "api_version": "capmesh.io/v1alpha1",
        "kind":        "agent",
        "name":        "python-security-reviewer",
        "namespace":   "security",
        "owner":       "python-guild",
        "version":     "1.0.0",
        "labels":      {"framework": "strands", "language": "python"}
    },
    "governance": {
        "status":      "approved",
        "visibility":  "organization",
        "environment": ["production", "staging"]
    },
    "interface": {
        "protocol": "a2a",
        "endpoint": "https://python-reviewer.acme.com"
    },
    "provides": [
        {
            "capability":  "security.code.review",
            "contract":    "v1",
            "description": "Python-specialized security review: type confusion, injection, async pitfalls"
        }
    ]
}

resp = httpx.post(
    "http://capmesh:8080/v1/providers/register",
    json=manifest,
    headers={"Authorization": "Bearer $CAPMESH_TOKEN"}
)
print(resp.json())
# Registration response (instant): { "status": "registered", "provider": "security/python-security-reviewer:1.0.0", "digest": "sha256:e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6", "capabilities_indexed": ["security.code.review/v1"], "immediately_resolvable": true } # Immediately, any agent resolving security.code.review sees it: $ capmesh providers security.code.review --contract v1 RANK NAME VERSION STATUS SELECTED 1 security/crewai-security-reviewer 3.1.0 approved YES (highest semver) 2 security/python-security-reviewer 1.0.0 approved no (would need 4.0.0 to win) 3 security/langgraph-security-reviewer 2.4.0 approved no 4 security/code-review-skill 1.2.0 approved no # Agents can discover the new Python reviewer without any restart or redeploy. # To make it the default, publish version 4.0.0 (higher than crewai:3.1.0). $ capmesh resolve security.code.review \ --constraint ">=1.0.0,<2.0.0" \ --caller python-pipeline \ --env production Selected: security/python-security-reviewer:1.0.0 (version constraint forces this specific provider)

10 Governance -- Policies, Visibility, Approval, Audit

Common myth: "Dynamic loading means losing control."
This is backwards. Without CapMesh, developers hardcode whatever tools they want -- no central control, no audit trail. With CapMesh, the platform team controls the registry. Nothing runs unless it has status: approved. Dynamic loading WITH governance = control at scale.

Approval Lifecycle

Every provider has a status in its governance block. Only approved providers are resolvable.

governance:
  status: approved      # approved | deprecated | revoked
StatusResolvableVisible in searchAudit trailUse case
approvedYesYesYesActive providers in production
deprecatedNoYesYesPhased out -- agents auto-fall-back to next best
revokedNoNoYesSecurity incident -- completely blocked

Changing status via CLI:

$ capmesh tool deprecate security/snyk-scanner:2.1.0 Deprecated security/snyk-scanner:2.1.0 Next resolve of security.static.analysis will fall back to semgrep-scanner:3.0.0 Audit event recorded: deprecated by platform-eng at 2026-09-23T10:14:55Z $ capmesh agent revoke security/compromised-agent:1.0.0 Revoked security/compromised-agent:1.0.0 Reason: security incident (supply-chain compromise detected) Provider immediately excluded from all future resolutions. Audit trail preserved. Digest: sha256:dead...beef

Environment Isolation

governance:
  environment: [production]          # staging callers CANNOT resolve this

A staging CI pipeline resolving database.write will NEVER get the production database provider. Automatic. No extra firewall rules, no middleware.

$ capmesh resolve database.write --env staging --caller staging-pipeline Step 5 -- Policy (env=staging) [SKIP] data/prod-postgres-writer:3.0.0 (environment: [production] only -- BLOCKED) [PASS] data/staging-postgres-writer:2.1.0 (environment: [production, staging] -- OK) Selected: data/staging-postgres-writer:2.1.0

Visibility Controls

governance:
  visibility: private           # only owner can resolve
  # visibility: organization   # only callers in same org as owner
  # visibility: public         # anyone
LevelWho can resolveUse case
publicAny caller with valid environmentShared platform tools
organizationCallers in the same org as the ownerTeam-internal tools
privateCallers whose identity matches the ownerSecurity-sensitive scanners, licensed tools
$ capmesh resolve security.vulnerability.report \ --caller external-contractor \ --env staging Step 5 -- Policy (visibility=organization) [SKIP] security/sonarcloud-scanner:1.4.0 caller=external-contractor not in org acme-corp -- BLOCKED Resolution: FAILED Error: no approved provider satisfies the request for caller=external-contractor

Version Pinning

Consumers can require a specific semver range, regardless of what version exists at the top of the registry.

import capmesh
mesh = capmesh.connect()

# Exact ID resolve with kind filter
result = mesh.resolve("security.code.review", kind="agent")

# For version constraints, use the CLI or raw HTTP API:
# capmesh resolve security.code.review --constraint ">=2.0.0,<3.0.0" --kind agent
$ capmesh resolve security.code.review \ --contract v1 \ --constraint ">=2.0.0,<3.0.0" \ --env production Step 6 -- Version constraint (>=2.0.0,<3.0.0) [SKIP] security/crewai-security-reviewer:3.1.0 (3.1.0 >= 3.0.0 -- out of range) [PASS] security/langgraph-security-reviewer:2.4.0 (2.4.0 satisfies >=2.0.0,<3.0.0) Selected: security/langgraph-security-reviewer:2.4.0

Immutable Versions

Once an approved version is pushed, its digest is locked. You cannot push different content under the same version number.

$ capmesh tool push --file ./tampered-scanner/manifest.yaml # manifest.yaml claims to be security/snyk-scanner:2.1.0 but has different content Error: version conflict security/snyk-scanner:2.1.0 already exists Existing digest: sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 Submitted digest: sha256:deadbeef00000000000000000000000000000000000000000000000000000000 To publish new content, use a new version number: security/snyk-scanner:2.1.1

Full Audit Trail

Every resolution is stored in SQLite with full candidate list.

GET http://capmesh:8080/v1/resolutions/res_8444e343826b
{
  "trace_id":              "res_8444e343826b",
  "timestamp":             "2026-09-23T14:32:15Z",
  "caller": {
    "identity":    "ci-pipeline",
    "environment": "production",
    "namespace":   "eng"
  },
  "requested_capability":  "security.code.review",
  "requested_contract":    "v1",
  "version_constraint":    null,
  "candidates_evaluated": [
    {
      "provider": "security/crewai-security-reviewer:3.1.0",
      "passed":   true,
      "reason":   "selected -- highest semver"
    },
    {
      "provider": "security/langgraph-security-reviewer:2.4.0",
      "passed":   true,
      "reason":   "available -- lower semver"
    },
    {
      "provider": "security/openai-reviewer:2.0.0",
      "passed":   false,
      "reason":   "governance.status=deprecated"
    }
  ],
  "selected_provider":     "security/crewai-security-reviewer:3.1.0",
  "protocol":              "a2a",
  "outcome":               "success",
  "resolution_ms":         16.0
}

Query all resolutions for a capability in the last hour:

GET http://capmesh:8080/v1/resolutions?capability=security.code.review&since=2026-09-23T13:00:00Z
{ "total": 23, "resolutions": [ { "trace_id": "res_8444e343826b", "caller": "ci-pipeline", "selected": "crewai:3.1.0", "outcome": "success", "ms": 16 }, { "trace_id": "res_7b3c2d1e0f9a", "caller": "sec-agent", "selected": "crewai:3.1.0", "outcome": "success", "ms": 12 }, { "trace_id": "res_6a2b1c0d9e8f", "caller": "dev-sandbox", "selected": null, "outcome": "failed", "ms": 8, "error": "no approved provider satisfies environment=dev" } ] }

11 API Reference

All endpoints are on http://<capmesh-host>:8080. Responses are JSON. The server returns standard HTTP status codes.

Registry Endpoints

MethodPathDescription
POST/v1/providers/registerRegister (push) a provider manifest
GET/v1/providers/{namespace}/{name}List all versions of a provider
GET/v1/providers/{namespace}/{name}/{version}Get a specific provider version
DELETE/v1/providers/{namespace}/{name}/{version}Revoke a provider version
PATCH/v1/providers/{namespace}/{name}/{version}/statusUpdate governance status
GET/v1/capabilities/{id}/providersList providers for a capability
POST/v1/searchKeyword / natural language search

POST /v1/providers/register

Request body: full manifest YAML/JSON as described in section 4.

POST /v1/providers/register
Content-Type: application/json

{ ...manifest object... }
# 201 Created
{
  "status":   "registered",
  "provider": "security/crewai-security-reviewer:3.1.0",
  "digest":   "sha256:3f9f55a4...",
  "capabilities_indexed": ["security.code.review/v1"],
  "immediately_resolvable": true
}

# 409 Conflict (version exists with different digest)
{
  "error":    "version_conflict",
  "message":  "security/crewai-security-reviewer:3.1.0 already exists with digest sha256:3f9f55a4...",
  "hint":     "Bump the version number to publish new content"
}

GET /v1/capabilities/{id}/providers

GET /v1/capabilities/security.code.review/providers?contract=v1&status=approved
{
  "capability":  "security.code.review",
  "contract":    "v1",
  "providers": [
    {
      "namespace": "security",
      "name":      "crewai-security-reviewer",
      "version":   "3.1.0",
      "protocol":  "a2a",
      "status":    "approved",
      "digest":    "sha256:3f9f55a4..."
    },
    {
      "namespace": "security",
      "name":      "langgraph-security-reviewer",
      "version":   "2.4.0",
      "protocol":  "a2a",
      "status":    "approved",
      "digest":    "sha256:9b2c71e8..."
    }
  ],
  "total": 2
}

POST /v1/search

POST /v1/search
{
  "query":   "security scan",
  "type":    "tool",
  "status":  "approved",
  "limit":   10
}
{
  "results": [
    {
      "namespace":    "security",
      "name":         "sonarcloud-scanner",
      "version":      "1.4.0",
      "kind":         "tool",
      "protocol":     "rest",
      "capabilities": ["security.static.analysis/v1", "security.vulnerability.report/v1"],
      "score":        0.91
    }
  ],
  "total": 1
}

Resolution Endpoints

MethodPathDescription
POST/v1/resolveResolve a capability to its best provider
POST/v1/needNatural language resolve ("notify the team")
POST/v1/discoverRanked list of matches for exploration
GET/v1/resolutions/{trace_id}Get full trace for one resolution
GET/v1/resolutionsQuery resolution history (filter by capability, caller, time)

POST /v1/resolve

POST /v1/resolve
{
  "capability":          "security.code.review",
  "contract":            "v1",
  "version_constraint":  ">=2.0.0",
  "caller": {
    "identity":          "ci-pipeline",
    "environment":       "production",
    "namespace":         "eng"
  }
}
# 200 OK
{
  "status":          "resolved",
  "trace_id":        "res_8444e343826b",
  "capability":      "security.code.review",
  "contract":        "v1",
  "provider":        "security/crewai-security-reviewer:3.1.0",
  "protocol":        "a2a",
  "binding": {
    "connection": {
      "endpoint":    "https://crewai-security.acme.com",
      "framework":   "crewai"
    }
  },
  "resolution_ms":   14,
  "selected_from":   3,
  "candidates": [
    { "provider": "security/crewai-security-reviewer:3.1.0",    "passed": true,  "reason": "selected" },
    { "provider": "security/langgraph-security-reviewer:2.4.0", "passed": true,  "reason": "lower semver" },
    { "provider": "security/code-review-skill:1.2.0",           "passed": true,  "reason": "lower semver" }
  ]
}

# 404 Not Found
{
  "status":  "failed",
  "error":   "no_provider",
  "message": "no approved provider satisfies security.code.review/v1 for env=dev",
  "trace_id": "res_0000000000001"
}

POST /v1/need (natural language)

POST /v1/need
{
  "query": "notify the team about a build failure",
  "caller": {
    "identity":    "ci-pipeline",
    "environment": "production"
  }
}
{
  "status":        "resolved",
  "matched_capability": "notification.send",
  "match_score":   0.88,
  "trace_id":      "res_2e3f4a5b6c7d",
  "provider":      "comms/slack-notifier:4.0.2",
  "protocol":      "mcp",
  "binding": {
    "connection": {
      "server":    "slack-mcp",
      "tool_name": "post_message"
    }
  },
  "resolution_ms": 18
}

Artifact Endpoints

MethodPathDescription
POST/v1/artifacts/publishPublish a SKILL.md or other artifact
GET/v1/artifacts/{ns}/{name}/{version}Retrieve an artifact (e.g., SKILL.md content)
GET/v1/artifacts/{ns}/{name}/{version}/digestGet digest for verification

Server Endpoints

MethodPathDescription
GET/healthzHealth check (returns 200 OK with {"status":"ok"})
GET/v1/statsRegistry statistics (provider count, resolution count)
GET/v1/capabilitiesList all known capability IDs
GET /healthz

{"status": "ok", "version": "0.9.0", "providers": 34, "resolutions_today": 1247}
GET /v1/stats

{
  "providers": {
    "total":      34,
    "approved":   28,
    "deprecated":  4,
    "revoked":     2
  },
  "capabilities": {
    "total_ids":  19
  },
  "resolutions": {
    "total":      94321,
    "today":      1247,
    "avg_ms":     15.4,
    "success_rate": 0.997
  }
}

12 Getting Started

Install

pip install capmesh
pip install "capmesh[server]"       # for the registry server component

Start the server

capmesh server start --port 8080
CapMesh Registry Server v0.9.0 Listening: 127.0.0.1:8080 Database: ./capmesh.db (new) [2026-09-23 09:00:01] INFO Server ready

Register your first provider

# 1. Write a manifest.yaml (see section 4 for full examples)
# 2. Build and push
capmesh tool build --directory ./my-tool/
capmesh tool push --file ./my-tool/manifest.yaml

# 3. Verify
capmesh tool inspect tools/my-tool:1.0.0

Resolve your first capability

capmesh resolve my.capability --caller test --env dev

Run the full demo

git clone https://github.com/capmesh/capmesh.git
cd capmesh
pip install -e ".[server,dev]"

python demo/registry/generate_providers.py   # generates 34 sample providers
python demo/app.py                           # runs the full orchestrator demo

# Step-by-step demos
python demo/01_build.py            # validate manifests, show digests
python demo/02_register.py         # register all providers
python demo/03_resolve.py          # resolve capabilities, show trace
python demo/04_benefits.py         # WITH vs WITHOUT comparison
python demo/05_production.py       # production HTTP API usage
python demo/06_governance.py       # status, visibility, version pinning
python demo/07_natural_language.py # mesh.need() demo

Run tests

pytest tests/ -v                           # 164 tests
pytest tests/ -v --cov=capmesh             # with coverage (87%)
Open source. Apache 2.0.
Contributions welcome at github.com/capmesh/capmesh.