Check a NOD capability
check_capabilityChecks if a business domain supports a specified action (e.g., order_food, book_appointment) by retrieving its NOD manifest and reporting endpoint, authentication, and policy constraints.
Instructions
Given a domain and an action (e.g. order_food, book_appointment, search_products, get_pricing, view_menu, book_table, check_status, create_account), fetches the business's NOD manifest and reports whether the action is supported, the endpoint URL, authentication requirements, and any policy constraints.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The domain to check (e.g. "demo-restaurant.localhost"). | |
| action | Yes | The action to check. Common values: order_food, place_order, view_menu, book_table, book_appointment, search_products, find_provider, get_pricing, check_inventory, check_status, create_account, get_docs, contact_support. |
Implementation Reference
- src/manifest.ts:360-429 (handler)The main handler function for check_capability. Takes a NodManifest and raw action string, normalizes the action, checks aliases, resolves endpoints, and returns a CapabilityResult indicating whether the action is supported.
export function checkCapability( manifest: NodManifest, rawAction: string, ): CapabilityResult { const normalized = normalizeAction(rawAction); const aliases = ACTION_ALIASES[normalized] ?? []; const tokens = [normalized, ...aliases]; const humanFallback = manifest.agent_policies?.human_fallback; for (const token of tokens) { const matched = matchCapability(manifest, token); if (matched) { const endpoint = resolveEndpointForToken(manifest, token); return { supported: true, action: rawAction, normalized_action: normalized, matched_via: matched, reason: `Manifest declares "${token}" under ${matched}.`, endpoint: endpoint?.url, method: endpoint?.method, authentication: endpoint?.authentication, constraints: collectConstraints(manifest, normalized), human_fallback: humanFallback, }; } } const structural = resolveEndpointForToken(manifest, normalized); if (structural) { return { supported: true, action: rawAction, normalized_action: normalized, matched_via: structural.source, reason: `Manifest provides a ${normalized} endpoint at ${structural.source}.`, endpoint: structural.url, method: structural.method, authentication: structural.authentication, constraints: collectConstraints(manifest, normalized), human_fallback: humanFallback, }; } for (const alias of aliases) { const hit = resolveEndpointForToken(manifest, alias); if (hit) { return { supported: true, action: rawAction, normalized_action: normalized, matched_via: hit.source, reason: `Manifest provides a related "${alias}" endpoint at ${hit.source}.`, endpoint: hit.url, method: hit.method, authentication: hit.authentication, constraints: collectConstraints(manifest, normalized), human_fallback: humanFallback, }; } } return { supported: false, action: rawAction, normalized_action: normalized, reason: `No capability or endpoint found for "${rawAction}". Direct the user to the business's website or contact channels.`, human_fallback: humanFallback, }; } - src/manifest.ts:315-326 (schema)The CapabilityResult interface defining the return type of checkCapability: supported boolean, action details, endpoint info, constraints, and human fallback.
export interface CapabilityResult { supported: boolean; action: string; normalized_action: string; reason: string; endpoint?: string; method?: string; authentication?: string; constraints?: Record<string, unknown>; matched_via?: string; human_fallback?: { url: string; description?: string }; } - src/index.ts:64-112 (registration)Registration of the 'check_capability' tool on the MCP server with input schema (domain, action) and the async handler that calls fetchManifest and checkCapability.
server.registerTool( "check_capability", { title: "Check a NOD capability", description: "Given a domain and an action (e.g. order_food, book_appointment, search_products, get_pricing, view_menu, book_table, check_status, create_account), fetches the business's NOD manifest and reports whether the action is supported, the endpoint URL, authentication requirements, and any policy constraints.", inputSchema: { domain: z .string() .min(1) .describe('The domain to check (e.g. "demo-restaurant.localhost").'), action: z .string() .min(1) .describe( "The action to check. Common values: order_food, place_order, view_menu, book_table, book_appointment, search_products, find_provider, get_pricing, check_inventory, check_status, create_account, get_docs, contact_support.", ), }, }, async ({ domain, action }) => { const fetched = await fetchManifest(domain); if ("error" in fetched) { return { isError: true, content: [ { type: "text", text: `Cannot check "${action}" — no NOD manifest found for ${domain}.\nTried:\n${fetched.tried_urls .map((u) => ` - ${u}`) .join("\n")}`, }, ], }; } const result = checkCapability(fetched.manifest, action); return { content: [ { type: "text", text: formatCapability(domain, result), }, { type: "text", text: "```json\n" + JSON.stringify(result, null, 2) + "\n```", }, ], }; }, ); - src/manifest.ts:438-567 (helper)Helper function resolveEndpointForToken that maps action tokens (e.g., 'purchase', 'booking', 'search') to their corresponding API endpoint from the manifest.
function resolveEndpointForToken( manifest: NodManifest, token: string, ): ResolvedEndpoint | null { const tx = manifest.transactions; const disc = manifest.discovery; const info = manifest.information; const sup = manifest.support; switch (token) { case "purchase": case "order": case "order_food": case "place_order": case "delivery": case "pickup": if (tx?.purchase?.endpoint) return { url: tx.purchase.endpoint, method: tx.purchase.method, authentication: tx.purchase.authentication, source: "transactions.purchase", }; break; case "booking": case "book_table": case "book_appointment": case "reservation": case "reserve": case "appointment": case "schedule": if (tx?.booking?.endpoint) return { url: tx.booking.endpoint, method: tx.booking.method, authentication: tx.booking.authentication, source: "transactions.booking", }; break; case "subscription": case "create_account": case "signup": case "account": if (tx?.subscription?.endpoint) return { url: tx.subscription.endpoint, method: tx.subscription.method, authentication: tx.subscription.authentication, source: "transactions.subscription", }; break; case "search": case "search_products": case "find_provider": case "provider_search": if (disc?.search?.endpoint) return { url: disc.search.endpoint, method: disc.search.method, authentication: disc.search.authentication, source: "discovery.search", }; break; case "menu": case "view_menu": case "browse_menu": case "catalog": if (disc?.catalog?.url) return { url: disc.catalog.url, method: "GET", source: "discovery.catalog", }; break; case "pricing": case "get_pricing": case "price": if (info?.pricing?.endpoint) return { url: info.pricing.endpoint, method: info.pricing.method ?? "GET", authentication: info.pricing.authentication, source: "information.pricing", }; break; case "inventory": case "in_stock": case "check_inventory": if (info?.inventory?.endpoint) return { url: info.inventory.endpoint, method: info.inventory.method ?? "GET", authentication: info.inventory.authentication, source: "information.inventory", }; break; case "hours": case "get_hours": if (info?.hours?.endpoint) return { url: info.hours.endpoint, method: info.hours.method ?? "GET", authentication: info.hours.authentication, source: "information.hours", }; break; case "order_tracking": case "check_status": case "status": case "track": if (sup?.order_tracking?.endpoint) return { url: sup.order_tracking.endpoint, method: sup.order_tracking.method ?? "GET", authentication: sup.order_tracking.authentication, source: "support.order_tracking", }; break; case "documentation": case "docs": case "get_docs": if (disc?.mcp_server?.url) return { url: disc.mcp_server.url, source: "discovery.mcp_server", }; break; } return null; } - src/manifest.ts:569-590 (helper)Helper function collectConstraints that gathers agent policy constraints (human confirmation, rate limits, booking restrictions) from the manifest for the given action.
function collectConstraints( manifest: NodManifest, action: string, ): Record<string, unknown> | undefined { const constraints: Record<string, unknown> = {}; const policies = manifest.agent_policies; if (policies?.require_human_confirmation) constraints.require_human_confirmation = policies.require_human_confirmation; if (policies?.rate_limits) constraints.rate_limits = policies.rate_limits; if (policies?.allow_automated_purchases !== undefined) constraints.allow_automated_purchases = policies.allow_automated_purchases; const tx = manifest.transactions; if (action === "book_table" || action === "book_appointment") { if (tx?.booking?.required_fields) constraints.required_fields = tx.booking.required_fields; if (tx?.booking?.max_party_size) constraints.max_party_size = tx.booking.max_party_size; } return Object.keys(constraints).length ? constraints : undefined; }