Skip to main content
Glama

Check a NOD capability

check_capability

Checks 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

TableJSON Schema
NameRequiredDescriptionDefault
domainYesThe domain to check (e.g. "demo-restaurant.localhost").
actionYesThe 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

  • 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,
      };
    }
  • 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```",
            },
          ],
        };
      },
    );
  • 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;
    }
  • 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;
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full behavioral disclosure. It explains what the tool does and returns, but does not mention side effects, prerequisites (e.g., domain validity), or that it is read-only.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence covering purpose, input, and output. Very concise with no wasted words, though slightly dense; could be broken into two sentences for readability, but still effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, but description adequately covers return fields (supported status, endpoint, auth, policies). Input is fully described. Missing error handling and sibling differentiation, but sufficient for the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds value by listing common actions, providing concrete examples that aid selection beyond the schema's generic string type.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool checks if an action is supported for a given domain, listing output details. It differentiates from the sibling 'lookup_nod' by focusing on a specific action check.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus 'lookup_nod' or when not to use it. The description only implies usage through examples, lacking explicit context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/opennod/nod-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server