Documentation Index
Fetch the complete documentation index at: https://docs.ezforge.ai/llms.txt
Use this file to discover all available pages before exploring further.
Overview
A composite skill aggregates capabilities from multiple MCP servers into a single discoverable unit. Instead of querying dozens of individual servers, an AI agent queries one composite that routes to the right businesses based on vertical, location, capabilities, and trust requirements.
Composite skills are computed in real-time — they reflect current health and verification status on every request.
Types of composite skills
Per-business composition
A single business with multiple capabilities exposes them as one unified skill. The listing’s SKILL.md references sub-skills via composed_of:
# SKILL.md — Maria's Italian Restaurant
name: marias-italian
description: Full-service Italian restaurant in downtown Ann Arbor
version: 1.0.0
verification_tier: 3
capabilities:
- menu_search
- reservation_booking
- dietary_filtering
- hours_inquiry
composed_of:
- uri: mcp://marias-italian.ready.ezforge.ai/menu
capability: menu_search
- uri: mcp://marias-italian.ready.ezforge.ai/booking
capability: reservation_booking
Cross-business composition (Hub-native)
Hub dynamically generates composites from registry queries — not static files, but computed at query time based on vertical, location, verification level, and capabilities:
# Dynamically generated composite
name: ann-arbor-restaurant-booking
description: Book a table at verified restaurants in Ann Arbor, MI
version: dynamic
generated_by: hub
query:
vertical: restaurant
location: { city: "Ann Arbor", state: "MI" }
capabilities: [reservation_booking]
verification_tier_min: 2
composed_of:
- uri: mcp://marias-italian.ready.ezforge.ai
name: "Maria's Italian"
verification_tier: 3
health_score: 98
- uri: mcp://sakura-sushi.ready.ezforge.ai
name: "Sakura Sushi"
verification_tier: 2
health_score: 95
Trust rules
A composite skill’s trust level equals the minimum verification tier of its participants (Decision #6). This prevents a single unverified server from hiding inside a trusted composite.
| Composite trust | Meaning |
|---|
| 1 — Unverified | At least one participant is unverified |
| 2 — Phone Verified | All participants are phone-verified or higher |
| 3 — Business Verified | All participants are business-verified or higher |
| 4 — Premium Verified | All participants are premium-verified |
Consequences:
- If a participant’s verification lapses, the composite is automatically recomputed excluding that participant
- Unhealthy servers (health score < 50) are excluded from composite membership entirely
- A composite’s
avgHealthScore is the average of its current members
Filter composites by minimum trust with ?verification_tier_min=3 — returns only composites where every participant is business-verified or higher.
created_by discriminator
Every composite has a created_by field that indicates its origin and governs its lifecycle:
| Value | Source | Visibility | Expires |
|---|
system | Auto-generated featured composites | Always public | Never |
user | Account holder created or promoted | Public or private | Never |
agent | Agent-created at runtime | Always private | 30 days |
Agent composites
When an agent creates a composite with created_by=agent:
- Visibility is always
private — the visibility parameter is rejected with HTTP 400
expiresAt is set to now() + 30 days
- Maximum 50 agent composites per account (HTTP 429 with
Retry-After: 86400 if exceeded)
- A daily background job purges expired agent composites
Account holders can promote an agent-created composite to persistent, public ownership:
Auth: Builder+ Hub API key (owning account)
PATCH /v1/hub/composites/{id}
Authorization: Bearer <hub-api-key>
Content-Type: application/json
{
"visibility": "public",
"created_by": "user"
}
Promotion clears expiresAt (the composite persists indefinitely) and makes it eligible for browse discovery.
Response:
{
"id": "01JQXYZ...",
"name": "Ann Arbor Lunch Options",
"description": "Quick lunch options near downtown Ann Arbor",
"visibility": "public",
"createdBy": "user",
"expiresAt": null,
"compositeTrust": 2,
"memberCount": 8,
"avgHealthScore": 95,
"createdAt": "2026-05-06T11:00:00Z",
"updatedAt": "2026-05-06T12:00:00Z"
}
Featured composites (created_by: system)
Hub auto-generates system composites every 6 hours:
- For each vertical with ≥ 3 eligible listings in a given city/state
- Eligibility:
verification_tier ≥ 2 and health_score ≥ 50
- Maximum 500 system composites system-wide
- Named
"{City} {Vertical Title-Case}" (e.g., “Ann Arbor Restaurants”)
- Stable deterministic IDs — safe to bookmark
- Always
visibility: public
API reference
Dynamic composite query
Query composites in real time without saving a composite definition:
Auth: Explorer+ Hub API key
Query parameters:
| Parameter | Type | Description |
|---|
vertical | string | Business vertical (e.g., restaurant, salon) |
city | string | City name |
state | string | State abbreviation (e.g., MI) |
zip | string | ZIP code |
capabilities | string | Comma-separated capability list (e.g., reservation_booking,menu_search) |
verification_tier_min | integer | Minimum participant verification tier (1–4) |
health_score_min | integer | Minimum participant health score (0–100) |
Example request:
GET /v1/hub/composites?vertical=restaurant&city=ann-arbor&state=mi&capabilities=reservation_booking&verification_tier_min=2
Authorization: Bearer hub_key_...
Response: A dynamically generated composite document listing all matching businesses, sorted by trust_score × health_score × listing_tier.
{
"name": "Ann Arbor Restaurant Booking",
"description": "Verified restaurants in Ann Arbor, MI offering reservation booking",
"version": "dynamic",
"composite_trust": 2,
"avg_health_score": 94,
"generated_at": "2026-05-06T12:00:00Z",
"composed_of": [
{
"listing_id": "01JQXYZ...",
"name": "Maria's Italian",
"verification_tier": 3,
"health_score": 98,
"listing_tier": "premium",
"capabilities": ["menu_search", "reservation_booking"],
"mcp_url": "mcp://marias-italian.ready.ezforge.ai"
},
{
"listing_id": "01JQABC...",
"name": "Sakura Sushi",
"verification_tier": 2,
"health_score": 91,
"listing_tier": "featured",
"capabilities": ["reservation_booking"],
"mcp_url": "mcp://sakura-sushi.ready.ezforge.ai"
}
]
}
Composites are computed fresh on every request — not cached — to reflect real-time health and verification status. Query performance target: <200ms p95.
List your composites
Return all saved composites owned by the authenticated account:
GET /v1/hub/composites?mine=true
Auth: Explorer+ Hub API key
Query parameters:
| Parameter | Type | Description |
|---|
mine | boolean | Must be true or 1 to enter owner-list mode |
created_by | string | Optional filter: agent, user, or system |
Page limit: The response returns up to 200 composites per call. When the result set is capped at 200, the response includes the X-Truncated: true header indicating that more records exist beyond the returned page.
X-Truncated response header:
| Header | Value | Meaning |
|---|
X-Truncated | true | Result set was capped at 200; additional composites exist. Re-query with narrower created_by filter or use paginated browse instead. |
| (absent) | — | Fewer than 200 composites were returned; result is complete. |
Example request:
GET /v1/hub/composites?mine=true&created_by=agent
Authorization: Bearer hub_key_...
Response:
{
"data": {
"composites": [
{
"id": "01JQXYZ...",
"name": "Ann Arbor Lunch Options",
"createdBy": "agent",
"visibility": "private",
"expiresAt": "2026-06-05T12:00:00Z",
"compositeTrust": 2,
"memberCount": 5,
"avgHealthScore": 91
}
]
}
}
If the response includes X-Truncated: true, your result is incomplete. Use created_by to narrow the filter, or use the browse endpoint with pagination for full traversal of public composites.
Create custom composite
Save a composite definition for reuse:
POST /v1/hub/composites/custom
Auth: Builder+ Hub API key
Request body:
| Field | Type | Required | Description |
|---|
name | string | Yes | Human-readable name |
description | string | Yes | What this composite does |
query_definition | object | Yes | Filter criteria (see below) |
visibility | string | No | "public" or "private" (default: "private") |
created_by | string | No | "user" (default) or "agent" |
query_definition fields:
| Field | Type | Description |
|---|
vertical | string | Business vertical |
city | string | City name |
state | string | State abbreviation |
zip | string | ZIP code |
capabilities | string[] | Required capability list |
verification_tier_min | integer | Minimum participant tier (1–4) |
health_score_min | integer | Minimum participant health score (0–100) |
Example — user-owned public composite:
POST /v1/hub/composites/custom
Authorization: Bearer hub_key_...
Content-Type: application/json
{
"name": "Detroit Date Night",
"description": "Restaurants and entertainment venues in downtown Detroit",
"query_definition": {
"vertical": "restaurant",
"city": "Detroit",
"state": "MI",
"capabilities": ["reservation_booking"],
"verification_tier_min": 2
},
"visibility": "public"
}
Example — agent-created ephemeral composite:
POST /v1/hub/composites/custom
Authorization: Bearer hub_key_...
Content-Type: application/json
{
"name": "Ann Arbor Lunch Options",
"description": "Quick lunch options near downtown Ann Arbor",
"created_by": "agent",
"query_definition": {
"vertical": "restaurant",
"city": "Ann Arbor",
"state": "MI"
}
}
Response:
{
"id": "01JQXYZ...",
"name": "Detroit Date Night",
"description": "Restaurants and entertainment venues in downtown Detroit",
"visibility": "public",
"createdBy": "user",
"expiresAt": null,
"compositeTrust": 2,
"memberCount": 12,
"avgHealthScore": 93,
"createdAt": "2026-05-06T12:00:00Z"
}
Browse public composites
List the public composite catalog — system-generated and user-promoted composites:
GET /v1/hub/composites/browse
Auth: Explorer+ Hub API key
Query parameters:
| Parameter | Type | Default | Description |
|---|
created_by | string | (both) | Filter by system or user |
page | integer | 1 | Page number (1-indexed) |
limit | integer | 20 | Results per page (max: 100) |
Agent-created composites (created_by: agent) are never included in browse results. Only public composites are returned.
Results are ranked: compositeTrust DESC → memberCount DESC → avgHealthScore DESC
Example request:
GET /v1/hub/composites/browse?created_by=system&page=1&limit=20
Authorization: Bearer hub_key_...
Response:
{
"composites": [
{
"id": "01JQXYZ...",
"name": "Ann Arbor Restaurants",
"description": "Auto-generated featured composite for restaurant businesses in Ann Arbor, MI.",
"visibility": "public",
"createdBy": "system",
"expiresAt": null,
"compositeTrust": 2,
"memberCount": 15,
"avgHealthScore": 92,
"queryDefinition": {
"vertical": "restaurant",
"city": "Ann Arbor",
"state": "MI",
"verification_tier_min": 2,
"health_score_min": 50
},
"createdAt": "2026-03-28T10:00:00Z",
"updatedAt": "2026-05-06T06:00:00Z"
}
],
"total": 47,
"page": 1,
"limit": 20
}
Composite SKILL.md
Every public composite exposes a SKILL.md document for agent discovery:
GET /v1/hub/composites/{id}/skill.md
Auth:
- Public composites: any Explorer+ key
- Private composites (including agent-created): owning account only
Response: A generated SKILL.md document with composite-specific hub fields:
name: Ann Arbor Restaurants
description: Auto-generated featured composite for restaurant businesses in Ann Arbor, MI.
version: dynamic
hub:
composite_id: "01JQXYZ..."
created_by: system
composite_trust: 2
member_count: 15
avg_health_score: 92
hub_url: "https://hub.ezforge.ai/composites/01JQXYZ..."
generated_at: "2026-05-06T12:00:00Z"
composed_of:
- name: "Maria's Italian"
uri: mcp://marias-italian.ready.ezforge.ai
verification_tier: 3
health_score: 98
- name: "Sakura Sushi"
uri: mcp://sakura-sushi.ready.ezforge.ai
verification_tier: 2
health_score: 91
# ... additional members
This document is regenerated on each request (consistent with Decision #7 — no caching).
The ezForge Hub MCP server exposes two composite tools for agents that consume Hub natively.
hub_composites
Query composites in real time using the dynamic composite API. Equivalent to GET /v1/hub/composites.
Arguments:
| Argument | Type | Required | Description |
|---|
api_key | string | No | Hub API key (Explorer+); falls back to HUB_API_KEY env var |
vertical | string | No | Business vertical |
city | string | No | City name |
state | string | No | State abbreviation |
zip | string | No | ZIP code |
capabilities | string | No | Comma-separated capability list |
verification_tier_min | string | No | Minimum participant verification tier |
health_score_min | string | No | Minimum participant health score |
Auth: Explorer+
hub_browse_composites
Browse the public composite catalog. Equivalent to GET /v1/hub/composites/browse. Agent-created composites are never included.
Arguments:
| Argument | Type | Required | Description |
|---|
api_key | string | No | Hub API key (Explorer+); falls back to HUB_API_KEY env var |
created_by | string | No | Filter: system or user (default: both) |
page | string | No | Page number (default: 1) |
limit | string | No | Results per page (default: 20, max: 100) |
Auth: Explorer+
Example response:
{
"composites": [
{
"id": "01JQXYZ...",
"name": "Detroit Restaurants",
"createdBy": "system",
"compositeTrust": 3,
"memberCount": 22,
"avgHealthScore": 94
}
],
"total": 47,
"page": 1,
"limit": 20
}
Auth requirements summary
| Endpoint | Required tier |
|---|
GET /v1/hub/composites | Explorer+ |
GET /v1/hub/composites?mine=true | Explorer+ |
GET /v1/hub/composites/browse | Explorer+ |
GET /v1/hub/composites/{id}/skill.md (public) | Explorer+ |
GET /v1/hub/composites/{id}/skill.md (private) | Owning account |
POST /v1/hub/composites/custom | Builder+ |
PATCH /v1/hub/composites/{id} (promote) | Builder+ (owning account) |
Hub MCP tools (hub_composites, hub_browse_composites) | Explorer+ |