Look up NOD manifest
lookup_nodFetch a business's NOD Protocol manifest to get its identity, capabilities, actions, APIs, and contacts.
Instructions
Fetches a business's NOD Protocol manifest from https://{domain}/.well-known/nod.json (or the local demo server for *.localhost domains) and returns a structured summary: business identity, declared capabilities, supported actions, API endpoints, and contact methods.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | The domain to look up (e.g. "example.com" or "demo-restaurant.localhost"). Do not include scheme or path. |
Implementation Reference
- src/index.ts:31-62 (handler)Handler function for the lookup_nod tool: fetches the NOD manifest from a domain, returns a text summary and JSON if successful, or an error message if not found.
async ({ domain }) => { const result = await fetchManifest(domain); if ("error" in result) { return { isError: true, content: [ { type: "text", text: `No NOD manifest found for ${domain}.\n\nTried:\n${result.tried_urls .map((u) => ` - ${u}`) .join( "\n", )}\n\nThis business has not published a nod.json manifest, or the domain is unreachable.`, }, ], }; } const summary = summarizeManifest(result.manifest, result.source_url); return { content: [ { type: "text", text: formatSummary(summary), }, { type: "text", text: "```json\n" + JSON.stringify(summary, null, 2) + "\n```", }, ], }; }, ); - src/index.ts:18-29 (schema)Input schema for lookup_nod: expects a single required string parameter 'domain' (e.g. example.com or demo-restaurant.localhost).
{ title: "Look up NOD manifest", description: "Fetches a business's NOD Protocol manifest from https://{domain}/.well-known/nod.json (or the local demo server for *.localhost domains) and returns a structured summary: business identity, declared capabilities, supported actions, API endpoints, and contact methods.", inputSchema: { domain: z .string() .min(1) .describe( 'The domain to look up (e.g. "example.com" or "demo-restaurant.localhost"). Do not include scheme or path.', ), }, - src/index.ts:16-62 (registration)Registration of the 'lookup_nod' tool on the MCP server with name, title, description, inputSchema, and handler callback.
server.registerTool( "lookup_nod", { title: "Look up NOD manifest", description: "Fetches a business's NOD Protocol manifest from https://{domain}/.well-known/nod.json (or the local demo server for *.localhost domains) and returns a structured summary: business identity, declared capabilities, supported actions, API endpoints, and contact methods.", inputSchema: { domain: z .string() .min(1) .describe( 'The domain to look up (e.g. "example.com" or "demo-restaurant.localhost"). Do not include scheme or path.', ), }, }, async ({ domain }) => { const result = await fetchManifest(domain); if ("error" in result) { return { isError: true, content: [ { type: "text", text: `No NOD manifest found for ${domain}.\n\nTried:\n${result.tried_urls .map((u) => ` - ${u}`) .join( "\n", )}\n\nThis business has not published a nod.json manifest, or the domain is unreachable.`, }, ], }; } const summary = summarizeManifest(result.manifest, result.source_url); return { content: [ { type: "text", text: formatSummary(summary), }, { type: "text", text: "```json\n" + JSON.stringify(summary, null, 2) + "\n```", }, ], }; }, ); - src/index.ts:114-152 (helper)formatSummary helper: formats the structured ManifestSummary into a human-readable text block with business info, capabilities, actions, endpoints, and contacts.
function formatSummary(s: ReturnType<typeof summarizeManifest>): string { const lines: string[] = []; lines.push(`# ${s.business_name} (${s.business_type})`); if (s.description) lines.push(s.description); lines.push(""); lines.push(`- URL: ${s.url}`); lines.push(`- Manifest: ${s.source_url}`); lines.push(`- NOD version: ${s.nod_version} (generated ${s.generated_at})`); if (s.capabilities.length) { lines.push(""); lines.push(`## Declared capabilities`); for (const c of s.capabilities) lines.push(` - ${c}`); } if (s.supported_actions.length) { lines.push(""); lines.push(`## Supported actions`); for (const a of s.supported_actions) { const auth = a.authentication ? ` [auth: ${a.authentication}]` : ""; lines.push(` - ${a.action} → ${a.endpoint ?? "(n/a)"}${auth}`); } } if (s.api_endpoints.length) { lines.push(""); lines.push(`## API endpoints`); for (const e of s.api_endpoints) { const auth = e.authentication ? ` [auth: ${e.authentication}]` : ""; lines.push(` - ${e.name}: ${e.method ?? ""} ${e.url}${auth}`); } } if (s.contact_methods.length) { lines.push(""); lines.push(`## Contact`); for (const c of s.contact_methods) { const agent = c.agent_compatible ? " (agent-compatible)" : ""; lines.push(` - ${c.channel}: ${c.value}${agent}`); } } return lines.join("\n"); } - src/manifest.ts:174-313 (helper)summarizeManifest helper: transforms raw NodManifest JSON into a structured ManifestSummary object with capabilities, supported actions, API endpoints, and contact methods.
export function summarizeManifest( manifest: NodManifest, sourceUrl: string, ): ManifestSummary { const capabilities: string[] = [ ...(manifest.transactions?.capabilities ?? []), ...(manifest.discovery?.mcp_server?.capabilities ?? []), ...(manifest.support?.contact?.mcp_server?.capabilities ?? []), ]; const supported_actions: SupportedAction[] = []; const api_endpoints: ApiEndpointSummary[] = []; const tx = manifest.transactions; if (tx?.purchase?.endpoint) { supported_actions.push({ action: "purchase", endpoint: tx.purchase.endpoint, authentication: tx.purchase.authentication, source: "transactions.purchase", }); api_endpoints.push({ name: "purchase", method: tx.purchase.method, url: tx.purchase.endpoint, authentication: tx.purchase.authentication, }); } if (tx?.booking?.endpoint) { supported_actions.push({ action: "booking", endpoint: tx.booking.endpoint, authentication: tx.booking.authentication, source: "transactions.booking", }); api_endpoints.push({ name: "booking", method: tx.booking.method, url: tx.booking.endpoint, authentication: tx.booking.authentication, }); } if (tx?.subscription?.endpoint) { supported_actions.push({ action: "subscription", endpoint: tx.subscription.endpoint, authentication: tx.subscription.authentication, source: "transactions.subscription", }); api_endpoints.push({ name: "subscription", method: tx.subscription.method, url: tx.subscription.endpoint, authentication: tx.subscription.authentication, }); } const disc = manifest.discovery; if (disc?.search?.endpoint) { supported_actions.push({ action: "search", endpoint: disc.search.endpoint, authentication: disc.search.authentication, source: "discovery.search", }); api_endpoints.push({ name: "search", method: disc.search.method, url: disc.search.endpoint, authentication: disc.search.authentication, }); } if (disc?.catalog?.url) { api_endpoints.push({ name: `catalog (${disc.catalog.type})`, method: "GET", url: disc.catalog.url, }); } const info = manifest.information; if (info?.pricing?.endpoint) { api_endpoints.push({ name: "pricing", method: info.pricing.method ?? "GET", url: info.pricing.endpoint, authentication: info.pricing.authentication, }); } if (info?.inventory?.endpoint) { api_endpoints.push({ name: "inventory", method: info.inventory.method ?? "GET", url: info.inventory.endpoint, authentication: info.inventory.authentication, }); } if (info?.hours?.endpoint) { api_endpoints.push({ name: "hours", method: info.hours.method ?? "GET", url: info.hours.endpoint, authentication: info.hours.authentication, }); } const contact_methods: ContactMethod[] = []; const general = manifest.business.contacts?.general; if (general?.email) contact_methods.push({ channel: "email", value: general.email }); if (general?.phone) contact_methods.push({ channel: "phone", value: general.phone }); const support = manifest.business.contacts?.support; if (support?.email) contact_methods.push({ channel: "support_email", value: support.email }); const supportChannels = manifest.support?.contact?.channels ?? []; for (const ch of supportChannels) { const type = String(ch.type ?? ""); const value = String(ch.url ?? ch.address ?? ch.number ?? ""); if (type && value) { contact_methods.push({ channel: type, value, agent_compatible: Boolean(ch.agent_compatible), }); } } return { business_name: manifest.business.name, business_type: manifest.business.type, description: manifest.business.description, url: manifest.business.url, nod_version: manifest.nod_version, generated_at: manifest.generated_at, source_url: sourceUrl, capabilities: Array.from(new Set(capabilities)), supported_actions, api_endpoints, contact_methods, }; }