@sonordev/site-kit 7.2.0 → 7.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/agent-manifest.json +6 -4
  3. package/dist/{AnalyticsProvider-SLFFBRPE.js → AnalyticsProvider-DJQA66AG.js} +4 -4
  4. package/dist/{ArticleViewTracker-TM5AMGN2.js → ArticleViewTracker-GFOAXFV7.js} +3 -3
  5. package/dist/{BlocksPopup-YJNJIVPO.js → BlocksPopup-AHDU34TL.js} +4 -4
  6. package/dist/{ChatWidget-XKOSH66S.js → ChatWidget-FHBAHFZX.js} +5 -5
  7. package/dist/{FileField-CI4UL5SH.js → FileField-J5W5MIAZ.js} +3 -3
  8. package/dist/{FormSpotlight-F2AAEGBN.js → FormSpotlight-PE5YZBFZ.js} +1 -1
  9. package/dist/{FormStage-BI5R5CNC.js → FormStage-OOPQC27J.js} +1 -1
  10. package/dist/{ManagedForm-G6COGHXL.js → ManagedForm-JRZAJ7SZ.js} +6 -6
  11. package/dist/{ManagedNewsletterForm-BO3WCGXX.js → ManagedNewsletterForm-TC5542ZG.js} +4 -4
  12. package/dist/{SignalCore-ZA6WHKBR.js → SignalCore-2YP5FCAS.js} +3 -3
  13. package/dist/{SiteChat-YJADDTKG.js → SiteChat-EGEZJJVV.js} +1 -1
  14. package/dist/{SiteDesignReporter-5YAW36AQ.js → SiteDesignReporter-YEEWJKWN.js} +5 -5
  15. package/dist/{SitePopups-ST5PMKZE.js → SitePopups-LQBIXIFV.js} +4 -4
  16. package/dist/SitemapSync-LSZ2EYOF.js +8 -0
  17. package/dist/_client/booking-widget.js +5 -5
  18. package/dist/affiliates/index.js +3 -3
  19. package/dist/analytics/index.js +4 -4
  20. package/dist/articles/index.js +1 -1
  21. package/dist/articles/server-ui.js +1 -1
  22. package/dist/chat/index.js +6 -6
  23. package/dist/{chunk-VO3JYRT5.js → chunk-2AD3CDRR.js} +8 -8
  24. package/dist/{chunk-BKY2ZNM7.js → chunk-2ECWEUHP.js} +1 -1
  25. package/dist/{chunk-F24FNCTK.js → chunk-56KNHB4U.js} +1 -1
  26. package/dist/{chunk-D6ZC7XKZ.js → chunk-BEBR4OJD.js} +2 -2
  27. package/dist/{chunk-S54ECQGY.js → chunk-CYUFBKJQ.js} +1 -1
  28. package/dist/{chunk-RPZ7OQGD.js → chunk-DNPNYWVL.js} +1 -1
  29. package/dist/{chunk-FR6BYFPC.js → chunk-EPT6FJUY.js} +1 -1
  30. package/dist/{chunk-JJ3DELUL.js → chunk-I2YX3HVD.js} +2 -2
  31. package/dist/{chunk-GGORNBSC.js → chunk-L7U23XI2.js} +1 -1
  32. package/dist/{chunk-JWTQS5F5.js → chunk-MKMD2HJW.js} +1 -1
  33. package/dist/{chunk-5YCEMV2L.js → chunk-MRQ2U4LZ.js} +1 -1
  34. package/dist/{chunk-OWZ7ATLZ.js → chunk-MVR4FY5R.js} +1 -1
  35. package/dist/{chunk-VHKEF5ZB.js → chunk-NI2XNEMR.js} +1 -1
  36. package/dist/{chunk-64DKGVEI.js → chunk-O5RGXTWU.js} +2 -2
  37. package/dist/{chunk-NV72HZ4W.js → chunk-RDPW4D33.js} +1 -1
  38. package/dist/{chunk-GEXT7BTE.js → chunk-T4DLETKR.js} +1 -1
  39. package/dist/{chunk-CF5QNFYU.js → chunk-UPRSH6Q4.js} +2 -2
  40. package/dist/{chunk-HGFAEDG3.js → chunk-VF4F5WXZ.js} +1 -1
  41. package/dist/{chunk-BC4Y3S3D.js → chunk-WDQB4OXY.js} +7 -3
  42. package/dist/{chunk-K4ZHAURD.js → chunk-WGG6GTKW.js} +1 -1
  43. package/dist/{chunk-IAM3D3RL.js → chunk-WGIDC6QP.js} +3 -3
  44. package/dist/{chunk-5V2V5C3Y.js → chunk-XLSQTTUE.js} +1 -1
  45. package/dist/{chunk-R46IQIGK.js → chunk-Y6LP36UW.js} +1 -1
  46. package/dist/{chunk-EJVQJCG5.js → chunk-YJLS6JBI.js} +2 -2
  47. package/dist/{chunk-QL6XNPSD.js → chunk-Z65DHMTW.js} +24 -7
  48. package/dist/{chunk-JMLK6MH7.js → chunk-ZHS2XFLV.js} +1 -1
  49. package/dist/{chunk-D5DCBD4Y.js → chunk-ZKHI4E2B.js} +1 -1
  50. package/dist/client/index.js +3 -3
  51. package/dist/commerce/index.js +4 -4
  52. package/dist/engage/index.js +7 -7
  53. package/dist/fleet/index.js +4 -4
  54. package/dist/forms/index.js +7 -7
  55. package/dist/forms/server.js +2 -2
  56. package/dist/images/index.js +4 -4
  57. package/dist/index.js +1 -1
  58. package/dist/layout/client.js +7 -7
  59. package/dist/layout/index.js +8 -8
  60. package/dist/llms/agent-access.d.ts +4 -0
  61. package/dist/llms/index.js +4 -4
  62. package/dist/maps/index.js +3 -3
  63. package/dist/mcp/WebMcpTools.d.ts +5 -4
  64. package/dist/mcp/client.js +14 -7
  65. package/dist/mcp/discovery.d.ts +48 -0
  66. package/dist/mcp/handlers.d.ts +13 -7
  67. package/dist/mcp/index.d.ts +5 -3
  68. package/dist/mcp/index.js +61 -17
  69. package/dist/mcp/serverCard.d.ts +6 -7
  70. package/dist/mcp/sonor.js +6 -6
  71. package/dist/revalidate/index.js +2 -2
  72. package/dist/seo/client.js +4 -4
  73. package/dist/seo/index.js +4 -4
  74. package/dist/seo/llms.js +4 -4
  75. package/dist/seo/register-sitemap-cli.js +1 -1
  76. package/dist/seo/sitemap.js +2 -2
  77. package/dist/server/index.js +2 -2
  78. package/dist/shared/version.d.ts +1 -1
  79. package/dist/signal/index.js +2 -2
  80. package/dist/sitemap/index.js +2 -2
  81. package/dist/sync/index.js +5 -5
  82. package/dist/website/images.js +4 -4
  83. package/dist/website/index.js +5 -5
  84. package/dist/website/popups.js +4 -4
  85. package/dist/{writeLLMsTxt-OV24LQVL.js → writeLLMsTxt-2NQVDGYI.js} +1 -1
  86. package/package.json +1 -1
  87. package/src/forms/README.md +2 -2
  88. package/src/llms/README.md +69 -0
  89. package/src/mcp/README.md +50 -16
  90. package/dist/SitemapSync-RJTEBINX.js +0 -8
package/dist/mcp/index.js CHANGED
@@ -2,6 +2,7 @@ import { MCP_SUPPORTED_PROTOCOL_VERSIONS, dispatch, errorOutcome, JSONRPC_INVALI
2
2
  export { JSONRPC_METHOD_NOT_FOUND, MCP_ERROR_HEADER_MISMATCH, MCP_ERROR_UNSUPPORTED_PROTOCOL_VERSION, MCP_PROTOCOL_VERSIONS_LEGACY, MCP_PROTOCOL_VERSION_MODERN, MCP_SUPPORTED_PROTOCOL_VERSIONS, META_CLIENT_INFO, META_PROTOCOL_VERSION, META_SERVER_INFO, dispatch, isSupportedVersion, toToolDescriptor, toToolResult, toolErrorResult, validateArgs } from '../chunk-FYAB6CXS.js';
3
3
  export { declarativeToolField, declarativeToolForm } from '../chunk-HW7B43E5.js';
4
4
  import '../chunk-PKBMQBKP.js';
5
+ import { createHash } from 'crypto';
5
6
 
6
7
  // src/mcp/types.ts
7
8
  function defineMcpTool(tool) {
@@ -10,6 +11,7 @@ function defineMcpTool(tool) {
10
11
 
11
12
  // src/mcp/serverCard.ts
12
13
  var MCP_SERVER_CARD_SCHEMA = "https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json";
14
+ var MCP_SERVER_CARD_MEDIA_TYPE = "application/mcp-server-card+json";
13
15
  var MCP_SERVER_CARD_PATH = "/.well-known/mcp-server-card";
14
16
  var MCP_SERVER_CARD_LEGACY_PATH = "/.well-known/mcp.json";
15
17
  var SITE_KIT_CARD_META_KEY = "io.sonor.site-kit/tools";
@@ -70,6 +72,60 @@ function validateMcpServerCard(card) {
70
72
  }
71
73
  return problems;
72
74
  }
75
+ var MCP_AI_CATALOG_PATH = "/.well-known/ai-catalog.json";
76
+ var MCP_AI_CATALOG_MEDIA_TYPE = "application/ai-catalog+json";
77
+ function buildMcpAiCatalog(options) {
78
+ const base = new URL(options.baseUrl);
79
+ if (!["http:", "https:"].includes(base.protocol) || base.username || base.password || base.search || base.hash || base.pathname !== "/") {
80
+ throw new Error("baseUrl must be an explicit HTTP(S) origin without credentials, query or fragment");
81
+ }
82
+ const name = /^[^/\s]+\/([^/\s]+)$/.exec(options.info.name)?.[1];
83
+ if (!name) {
84
+ throw new Error('info.name must have a namespace and server name, e.g. "io.example/weather"');
85
+ }
86
+ const path = options.serverCardPath;
87
+ if (!path || path.startsWith("//") || path.includes("\\") || /^[a-z][a-z\d+.-]*:/i.test(path)) {
88
+ throw new Error("serverCardPath must be an origin-relative path");
89
+ }
90
+ const cardUrl = new URL(path.startsWith("/") ? path : `/${path}`, base);
91
+ if (cardUrl.hash) throw new Error("serverCardPath must not include a fragment");
92
+ return {
93
+ specVersion: "1.0",
94
+ entries: [{
95
+ identifier: `urn:air:${base.hostname}:mcp:${encodeURIComponent(name)}`,
96
+ type: MCP_SERVER_CARD_MEDIA_TYPE,
97
+ url: cardUrl.href
98
+ }]
99
+ };
100
+ }
101
+ function createMcpAiCatalogHandler(options) {
102
+ return createMcpDiscoveryHandlers(buildMcpAiCatalog(options), {
103
+ mediaType: MCP_AI_CATALOG_MEDIA_TYPE,
104
+ maxAge: options.maxAge
105
+ });
106
+ }
107
+ function createMcpDiscoveryHandlers(document, options) {
108
+ const body = `${JSON.stringify(document, null, 2)}
109
+ `;
110
+ const etag = `W/"${createHash("sha256").update(body).digest("base64url")}"`;
111
+ const maxAge = options.maxAge ?? 3600;
112
+ if (!Number.isSafeInteger(maxAge) || maxAge < 0) {
113
+ throw new Error("maxAge must be a non-negative integer");
114
+ }
115
+ const headers = {
116
+ "Content-Type": options.mediaType,
117
+ "Cache-Control": `public, max-age=${maxAge}`,
118
+ ETag: etag,
119
+ "Access-Control-Allow-Origin": "*",
120
+ "Access-Control-Allow-Methods": "GET, OPTIONS",
121
+ "Access-Control-Allow-Headers": "Accept, Content-Type, If-None-Match",
122
+ "Access-Control-Expose-Headers": "ETag"
123
+ };
124
+ return {
125
+ GET: async () => new Response(body, { status: 200, headers }),
126
+ OPTIONS: async () => new Response(null, { status: 204, headers })
127
+ };
128
+ }
73
129
 
74
130
  // src/mcp/handlers.ts
75
131
  var MCP_REQUEST_HEADERS = [
@@ -256,22 +312,10 @@ function createMcpHandler(options) {
256
312
  return { POST, GET: methodNotAllowed, DELETE: methodNotAllowed, OPTIONS };
257
313
  }
258
314
  function createMcpServerCardHandler(options) {
259
- const card = buildMcpServerCard(options);
260
- const body = `${JSON.stringify(card, null, 2)}
261
- `;
262
- const maxAge = options.maxAge ?? 3600;
263
- const headers = {
264
- "Content-Type": "application/json",
265
- "Cache-Control": `public, max-age=${maxAge}`,
266
- // The card is a discovery document — it is meant to be fetched by anyone.
267
- "Access-Control-Allow-Origin": "*",
268
- "Access-Control-Allow-Methods": "GET, OPTIONS",
269
- "Access-Control-Allow-Headers": "Content-Type"
270
- };
271
- return {
272
- GET: async () => new Response(body, { status: 200, headers }),
273
- OPTIONS: async () => new Response(null, { status: 204, headers })
274
- };
315
+ return createMcpDiscoveryHandlers(buildMcpServerCard(options), {
316
+ mediaType: options.contentType ?? "application/json",
317
+ maxAge: options.maxAge
318
+ });
275
319
  }
276
320
 
277
- export { MCP_SERVER_CARD_LEGACY_PATH, MCP_SERVER_CARD_PATH, MCP_SERVER_CARD_SCHEMA, SITE_KIT_CARD_META_KEY, WEBMCP_SURFACE_HEADER, buildMcpServerCard, createMcpHandler, createMcpServerCardHandler, decodeHeaderValue, defineMcpTool, toolCallRecord, validateMcpServerCard };
321
+ export { MCP_AI_CATALOG_MEDIA_TYPE, MCP_AI_CATALOG_PATH, MCP_SERVER_CARD_LEGACY_PATH, MCP_SERVER_CARD_MEDIA_TYPE, MCP_SERVER_CARD_PATH, MCP_SERVER_CARD_SCHEMA, SITE_KIT_CARD_META_KEY, WEBMCP_SURFACE_HEADER, buildMcpAiCatalog, buildMcpServerCard, createMcpAiCatalogHandler, createMcpHandler, createMcpServerCardHandler, decodeHeaderValue, defineMcpTool, toolCallRecord, validateMcpServerCard };
@@ -11,16 +11,15 @@
11
11
  * with enough identity attached that a human reviewing the connection knows
12
12
  * what they're approving.
13
13
  *
14
- * ── The two paths ─────────────────────────────────────────────────────────
15
- * SEP-1649 originally proposed `/.well-known/mcp.json`. The ratified SEP-2127
16
- * moved to `/.well-known/mcp-server-card`. Plenty of deployed crawlers and
17
- * validators still probe the old path, and serving one JSON document from two
18
- * URLs costs nothing, so `createMcpServerCardHandler` is mounted at both.
19
- * `mcp-server-card` is the canonical one; `mcp.json` is compatibility.
14
+ * The existing well-known paths stay available for compatibility. The newer
15
+ * experimental discovery draft uses a domain AI Catalog pointing to a card
16
+ * URL, with `<streamable-http-url>/server-card` as its recommended location.
17
+ * Hosts can mount the same card handler there without changing the old URLs.
20
18
  */
21
19
  import type { McpServerIcon, McpServerInfo, SiteKitMcpTool } from './types';
22
20
  export declare const MCP_SERVER_CARD_SCHEMA = "https://static.modelcontextprotocol.io/schemas/v1/server-card.schema.json";
23
- /** Canonical well-known path (SEP-2127). */
21
+ export declare const MCP_SERVER_CARD_MEDIA_TYPE = "application/mcp-server-card+json";
22
+ /** Existing site-kit well-known path; retained for backward compatibility. */
24
23
  export declare const MCP_SERVER_CARD_PATH = "/.well-known/mcp-server-card";
25
24
  /** Superseded SEP-1649 path, still widely probed. */
26
25
  export declare const MCP_SERVER_CARD_LEGACY_PATH = "/.well-known/mcp.json";
package/dist/mcp/sonor.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { toolErrorResult } from '../chunk-FYAB6CXS.js';
2
2
  import { fetchReviews, fetchReviewStats } from '../chunk-EDYHROQ7.js';
3
3
  import { getOfferings } from '../chunk-G3NHWMP5.js';
4
- import { fetchBookingTypes, fetchAvailability } from '../chunk-BKY2ZNM7.js';
4
+ import { fetchBookingTypes, fetchAvailability } from '../chunk-2ECWEUHP.js';
5
5
  import { getLLMsData, getServices, getFAQItems, getPageSummaries } from '../chunk-6U3VLV2C.js';
6
- import { getFormConfig } from '../chunk-5V2V5C3Y.js';
7
- import '../chunk-OWZ7ATLZ.js';
6
+ import { getFormConfig } from '../chunk-XLSQTTUE.js';
7
+ import '../chunk-MVR4FY5R.js';
8
8
  import '../chunk-YC7ELZS3.js';
9
9
  import '../chunk-ZTLMPUO6.js';
10
10
  import '../chunk-DXO6SBMD.js';
@@ -25,9 +25,9 @@ import '../chunk-C2FZBUSS.js';
25
25
  import '../chunk-5SQK3D53.js';
26
26
  import '../chunk-HW7B43E5.js';
27
27
  import '../chunk-NJCTQH2P.js';
28
- import '../chunk-D6ZC7XKZ.js';
29
- import '../chunk-K4ZHAURD.js';
30
- import { SITE_KIT_VERSION } from '../chunk-F24FNCTK.js';
28
+ import '../chunk-BEBR4OJD.js';
29
+ import '../chunk-WGG6GTKW.js';
30
+ import { SITE_KIT_VERSION } from '../chunk-56KNHB4U.js';
31
31
  import '../chunk-PKBMQBKP.js';
32
32
  import 'server-only';
33
33
  import { after } from 'next/server.js';
@@ -1,7 +1,7 @@
1
- import { createSeoRevalidationHandler } from '../chunk-VHKEF5ZB.js';
1
+ import { createSeoRevalidationHandler } from '../chunk-NI2XNEMR.js';
2
2
  import '../chunk-XTRZGXB2.js';
3
3
  export { SITE_CACHE_TAGS, SITE_REVALIDATE_PATH, isSiteRevalidatePong } from '../chunk-RYVDGXC2.js';
4
- import '../chunk-F24FNCTK.js';
4
+ import '../chunk-56KNHB4U.js';
5
5
  import '../chunk-PKBMQBKP.js';
6
6
 
7
7
  // src/revalidate/index.ts
@@ -1,9 +1,9 @@
1
1
  'use client';
2
- export { SitemapSync } from '../chunk-GEXT7BTE.js';
2
+ export { SitemapSync } from '../chunk-T4DLETKR.js';
3
3
  import '../chunk-YVKRYQRG.js';
4
4
  import '../chunk-43OCZ3JA.js';
5
5
  import '../chunk-EKBEOXTH.js';
6
- import '../chunk-D6ZC7XKZ.js';
7
- import '../chunk-K4ZHAURD.js';
8
- import '../chunk-F24FNCTK.js';
6
+ import '../chunk-BEBR4OJD.js';
7
+ import '../chunk-WGG6GTKW.js';
8
+ import '../chunk-56KNHB4U.js';
9
9
  import '../chunk-PKBMQBKP.js';
package/dist/seo/index.js CHANGED
@@ -2,7 +2,7 @@ export { ManagedNoScripts, ManagedScripts } from '../chunk-MVLMXC44.js';
2
2
  import { pickManagedLlmSchemaForJsonLd } from '../chunk-NZ4RXN3G.js';
3
3
  import { safeJsonLd } from '../chunk-4KZ6W3ZH.js';
4
4
  import { withoutSchemaPlaceholders } from '../chunk-VWWITFWM.js';
5
- export { SitemapSync } from '../chunk-GEXT7BTE.js';
5
+ export { SitemapSync } from '../chunk-T4DLETKR.js';
6
6
  import { getManagedMetadata } from '../chunk-4YTYGG2C.js';
7
7
  export { generateSitemap, getABVariant, getManagedMetadata, getManagedMetadataWithAB, getRedirect, getRobotsDirective, isIndexable } from '../chunk-4YTYGG2C.js';
8
8
  import { getContentBlock, getSchemaMarkups, getSEOPageData, getEntityEnhancedSchema, getFAQData, getInternalLinks, getEntities, pruneSchemaTypes } from '../chunk-662ILEZ6.js';
@@ -18,9 +18,9 @@ import '../chunk-FESKKJAS.js';
18
18
  import '../chunk-A4CC4ZG3.js';
19
19
  import '../chunk-43OCZ3JA.js';
20
20
  import '../chunk-EKBEOXTH.js';
21
- import '../chunk-D6ZC7XKZ.js';
22
- import '../chunk-K4ZHAURD.js';
23
- import '../chunk-F24FNCTK.js';
21
+ import '../chunk-BEBR4OJD.js';
22
+ import '../chunk-WGG6GTKW.js';
23
+ import '../chunk-56KNHB4U.js';
24
24
  import '../chunk-PKBMQBKP.js';
25
25
  import { Suspense } from 'react';
26
26
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
package/dist/seo/llms.js CHANGED
@@ -1,10 +1,10 @@
1
- export { createLLMsFullTxtHandler, createLLMsTxtHandler, formatSourcedFactsSection, llmsResponseHeaders } from '../chunk-BC4Y3S3D.js';
1
+ export { createLLMsFullTxtHandler, createLLMsTxtHandler, formatSourcedFactsSection, llmsResponseHeaders } from '../chunk-WDQB4OXY.js';
2
2
  export { buildAiDiscoveryHeaders, wantsLlmsDiscoveryLink } from '../chunk-PO2TRJPY.js';
3
3
  export { AI_RETRIEVAL_CRAWLERS, AI_TRAINING_CRAWLERS, buildAiCrawlerRules, createRobotsTxtHandler } from '../chunk-QLTDFUJ7.js';
4
- export { LEGACY_PUBLICATION_PATH, SEO_REVALIDATION_MAX_BODY_BYTES, SEO_REVALIDATION_MAX_ITEMS, createLlmsRevalidateHandler, createSeoRevalidationHandler, parseSeoRevalidationPayload } from '../chunk-VHKEF5ZB.js';
4
+ export { LEGACY_PUBLICATION_PATH, SEO_REVALIDATION_MAX_BODY_BYTES, SEO_REVALIDATION_MAX_ITEMS, createLlmsRevalidateHandler, createSeoRevalidationHandler, parseSeoRevalidationPayload } from '../chunk-NI2XNEMR.js';
5
5
  import '../chunk-XTRZGXB2.js';
6
6
  export { AEOBlock, AEOCitedContent, AEOClaim, AEOComparison, AEODefinition, AEOEntity, AEOProvenanceList, AEOStep, AEOSteps, AEOSummary, DEFAULT_SPEAKABLE_SELECTORS, SpeakableSchema, createSpeakableSchema, getSpeakableSelectorsForPage } from '../chunk-PSAG45YF.js';
7
- export { AGENT_ACCESS_HEADING, appendAgentAccessSection, describesMcp, detectMcpServer, formatAgentAccessSection, generateLLMsFullTxt, generateLLMsTxt, writeLLMsTxtToPublic } from '../chunk-QL6XNPSD.js';
7
+ export { AGENT_ACCESS_HEADING, appendAgentAccessSection, describesMcp, detectMcpServer, formatAgentAccessSection, generateLLMsFullTxt, generateLLMsTxt, writeLLMsTxtToPublic } from '../chunk-Z65DHMTW.js';
8
8
  export { getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices } from '../chunk-6U3VLV2C.js';
9
9
  import '../chunk-L5UOHS6E.js';
10
10
  import '../chunk-WMVK77ND.js';
@@ -15,5 +15,5 @@ import '../chunk-MJP63SSS.js';
15
15
  import '../chunk-YVKRYQRG.js';
16
16
  import '../chunk-FESKKJAS.js';
17
17
  import '../chunk-A4CC4ZG3.js';
18
- import '../chunk-F24FNCTK.js';
18
+ import '../chunk-56KNHB4U.js';
19
19
  import '../chunk-PKBMQBKP.js';
@@ -458,7 +458,7 @@ async function registerLocalSitemap(options) {
458
458
  }
459
459
  if (options.writeLlms && result.success) {
460
460
  try {
461
- const { writeLLMsTxtToPublic } = await import('../writeLLMsTxt-OV24LQVL.js');
461
+ const { writeLLMsTxtToPublic } = await import('../writeLLMsTxt-2NQVDGYI.js');
462
462
  const written = await writeLLMsTxtToPublic({
463
463
  // Resolved here too: the sync's own `site` is scoped to the branch that
464
464
  // posts, and this runs on the skip path as well.
@@ -1,6 +1,6 @@
1
- export { createSitemap, getPortfolioPaths, syncSitemapToPortal } from '../chunk-R46IQIGK.js';
1
+ export { createSitemap, getPortfolioPaths, syncSitemapToPortal } from '../chunk-Y6LP36UW.js';
2
2
  import '../chunk-Z22QVHT4.js';
3
- import '../chunk-QL6XNPSD.js';
3
+ import '../chunk-Z65DHMTW.js';
4
4
  import '../chunk-6U3VLV2C.js';
5
5
  import '../chunk-L5UOHS6E.js';
6
6
  import '../chunk-WMVK77ND.js';
@@ -1,6 +1,6 @@
1
- export { resolveClientCredential } from '../chunk-RPZ7OQGD.js';
1
+ export { resolveClientCredential } from '../chunk-DNPNYWVL.js';
2
2
  import '../chunk-VX5CMNMM.js';
3
3
  export { requireServerApiConfig, resolveApiOrigin, resolveServerApiConfig, serverApiFetch } from '../chunk-X6F6SO4S.js';
4
4
  import '../chunk-MH2DSGC6.js';
5
- import '../chunk-F24FNCTK.js';
5
+ import '../chunk-56KNHB4U.js';
6
6
  import '../chunk-PKBMQBKP.js';
@@ -7,4 +7,4 @@
7
7
  * it matches package.json at publish time, and version.test.ts asserts it in
8
8
  * dev, so it can't silently drift.
9
9
  */
10
- export declare const SITE_KIT_VERSION = "7.2.0";
10
+ export declare const SITE_KIT_VERSION = "7.3.0";
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- import { useSignalExperiment, useSignalEvent } from '../chunk-S54ECQGY.js';
3
- export { SignalBridge, useSignal, useSignalConfig, useSignalEvent, useSignalExperiment, useSignalOutcome } from '../chunk-S54ECQGY.js';
2
+ import { useSignalExperiment, useSignalEvent } from '../chunk-CYUFBKJQ.js';
3
+ export { SignalBridge, useSignal, useSignalConfig, useSignalEvent, useSignalExperiment, useSignalOutcome } from '../chunk-CYUFBKJQ.js';
4
4
  import '../chunk-PKBMQBKP.js';
5
5
  import React, { useEffect } from 'react';
6
6
  import { jsx, Fragment } from 'react/jsx-runtime';
@@ -1,6 +1,6 @@
1
- export { createSitemap, getPortfolioPaths, syncSitemapToPortal } from '../chunk-R46IQIGK.js';
1
+ export { createSitemap, getPortfolioPaths, syncSitemapToPortal } from '../chunk-Y6LP36UW.js';
2
2
  import '../chunk-Z22QVHT4.js';
3
- import '../chunk-QL6XNPSD.js';
3
+ import '../chunk-Z65DHMTW.js';
4
4
  import '../chunk-6U3VLV2C.js';
5
5
  import '../chunk-L5UOHS6E.js';
6
6
  import '../chunk-WMVK77ND.js';
@@ -1,6 +1,6 @@
1
- export { BookingWidget } from '../chunk-GGORNBSC.js';
2
- export { createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, prepareMeeting, releaseSlotHold } from '../chunk-BKY2ZNM7.js';
3
- import '../chunk-D6ZC7XKZ.js';
4
- import '../chunk-K4ZHAURD.js';
5
- import '../chunk-F24FNCTK.js';
1
+ export { BookingWidget } from '../chunk-L7U23XI2.js';
2
+ export { createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, prepareMeeting, releaseSlotHold } from '../chunk-2ECWEUHP.js';
3
+ import '../chunk-BEBR4OJD.js';
4
+ import '../chunk-WGG6GTKW.js';
5
+ import '../chunk-56KNHB4U.js';
6
6
  import '../chunk-PKBMQBKP.js';
@@ -1,6 +1,6 @@
1
- export { ManagedImage, assignImageToSlot, clearImageSlot, fetchManagedImage, fetchManagedImages, listImageFiles, uploadImage } from '../chunk-JMLK6MH7.js';
1
+ export { ManagedImage, assignImageToSlot, clearImageSlot, fetchManagedImage, fetchManagedImages, listImageFiles, uploadImage } from '../chunk-ZHS2XFLV.js';
2
2
  export { ManagedFavicon, getManagedFaviconUrl } from '../chunk-GW7GSBO7.js';
3
- import '../chunk-D6ZC7XKZ.js';
4
- import '../chunk-K4ZHAURD.js';
5
- import '../chunk-F24FNCTK.js';
3
+ import '../chunk-BEBR4OJD.js';
4
+ import '../chunk-WGG6GTKW.js';
5
+ import '../chunk-56KNHB4U.js';
6
6
  import '../chunk-PKBMQBKP.js';
@@ -1,13 +1,13 @@
1
1
  'use client';
2
- export { SiteDesignReporter } from '../chunk-5YCEMV2L.js';
3
- export { SITE_DESIGN_PATH, cleanFontStack, colorToHex, getSiteDesignTokens, measureSiteDesign, readDeclaredDesign, sendSiteDesign } from '../chunk-JJ3DELUL.js';
2
+ export { SiteDesignReporter } from '../chunk-MRQ2U4LZ.js';
3
+ export { SITE_DESIGN_PATH, cleanFontStack, colorToHex, getSiteDesignTokens, measureSiteDesign, readDeclaredDesign, sendSiteDesign } from '../chunk-I2YX3HVD.js';
4
4
  export { DEFAULT_POPUP_TOKENS, PopupBlocks } from '../chunk-BF7TZYC3.js';
5
5
  import '../chunk-IHG36STL.js';
6
6
  import '../chunk-YC7ELZS3.js';
7
7
  import '../chunk-S22FSH7C.js';
8
8
  import '../chunk-43OCZ3JA.js';
9
9
  import '../chunk-EKBEOXTH.js';
10
- import '../chunk-D6ZC7XKZ.js';
11
- import '../chunk-K4ZHAURD.js';
12
- import '../chunk-F24FNCTK.js';
10
+ import '../chunk-BEBR4OJD.js';
11
+ import '../chunk-WGG6GTKW.js';
12
+ import '../chunk-56KNHB4U.js';
13
13
  import '../chunk-PKBMQBKP.js';
@@ -1,14 +1,14 @@
1
1
  'use client';
2
2
  export { DEFAULT_POPUP_TOKENS, PopupBlocks } from '../chunk-BF7TZYC3.js';
3
3
  import '../chunk-IHG36STL.js';
4
- export { SitePopups } from '../chunk-EJVQJCG5.js';
4
+ export { SitePopups } from '../chunk-YJLS6JBI.js';
5
5
  import '../chunk-27FISYK4.js';
6
6
  import '../chunk-S22FSH7C.js';
7
7
  import '../chunk-24QZEO3Q.js';
8
8
  import '../chunk-GJWI74ZZ.js';
9
9
  import '../chunk-43OCZ3JA.js';
10
10
  import '../chunk-EKBEOXTH.js';
11
- import '../chunk-D6ZC7XKZ.js';
12
- import '../chunk-K4ZHAURD.js';
13
- import '../chunk-F24FNCTK.js';
11
+ import '../chunk-BEBR4OJD.js';
12
+ import '../chunk-WGG6GTKW.js';
13
+ import '../chunk-56KNHB4U.js';
14
14
  import '../chunk-PKBMQBKP.js';
@@ -1,4 +1,4 @@
1
- export { writeLLMsTxtToPublic } from './chunk-QL6XNPSD.js';
1
+ export { writeLLMsTxtToPublic } from './chunk-Z65DHMTW.js';
2
2
  import './chunk-6U3VLV2C.js';
3
3
  import './chunk-L5UOHS6E.js';
4
4
  import './chunk-WMVK77ND.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonordev/site-kit",
3
- "version": "7.2.0",
3
+ "version": "7.3.0",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@11.5.3",
6
6
  "description": "Complete client-side integration kit for Sonor - SEO, Analytics, Engage, Forms, Blog",
@@ -242,8 +242,8 @@ nothing to configure.
242
242
  - **Agent-sent leads are tagged.** When the browser reports that an agent
243
243
  pressed submit (`SubmitEvent.agentInvoked`), the submission carries that
244
244
  flag and the lead is tagged in Sonor, so you can see how those leads compare
245
- over time. It's the browser's word, so it never changes how a submission is
246
- checked. The agent is handed the outcome of its submit (`respondWith`).
245
+ over time, and Sonor's spam screening takes it into account. The agent is
246
+ handed the outcome of its submit (`respondWith`).
247
247
  - **Nothing typed before the form loads is lost.** `ServerForm` renders the
248
248
  form in the page HTML and loads the interactive version at idle. Since
249
249
  7.2.0, typing into the server-rendered form starts that upgrade at once and
@@ -229,6 +229,75 @@ with `optimizedLLMsTxt: false` in `createSitemap`, so one writer owns the file.
229
229
  Reads behind this write always bypass Next's Data Cache — hosts persist it
230
230
  between builds, and a cached read is how a site shipped a months-old llms.txt.
231
231
 
232
+ #### Agent discovery for a custom MCP server
233
+
234
+ A custom server stays opt-in. Share the same `mcp` options between the
235
+ build-time writer and both route handlers so the short and full files point
236
+ at the same tools. This adds links to an existing server; it doesn't create
237
+ the endpoint, card, or catalog.
238
+
239
+ ```ts
240
+ // lib/agent-access.ts
241
+ import type { AgentAccessOptions } from '@sonordev/site-kit/seo/llms'
242
+
243
+ export const agentAccess: AgentAccessOptions = {
244
+ endpoint: '/api/mcp',
245
+ card: '/api/mcp/server-card',
246
+ catalog: '/.well-known/ai-catalog.json', // omit unless this document is served
247
+ position: 'after-intro',
248
+ }
249
+ ```
250
+
251
+ ```ts
252
+ // The site's build-time writer
253
+ import { writeLLMsTxtToPublic } from '@sonordev/site-kit/seo/llms'
254
+ import { agentAccess } from '../lib/agent-access'
255
+
256
+ await writeLLMsTxtToPublic({
257
+ full: true,
258
+ site: 'example.com',
259
+ mcp: agentAccess,
260
+ })
261
+ ```
262
+
263
+ ```ts
264
+ // app/llms.txt/route.ts
265
+ import { createLLMsTxtHandler } from '@sonordev/site-kit/seo/llms'
266
+ import { agentAccess } from '@/lib/agent-access'
267
+
268
+ export const GET = createLLMsTxtHandler({
269
+ baseUrl: 'https://example.com',
270
+ mcp: agentAccess,
271
+ })
272
+ ```
273
+
274
+ ```ts
275
+ // app/llms-full.txt/route.ts — use the same options
276
+ import { createLLMsFullTxtHandler } from '@sonordev/site-kit/seo/llms'
277
+ import { agentAccess } from '@/lib/agent-access'
278
+
279
+ export const GET = createLLMsFullTxtHandler({
280
+ baseUrl: 'https://example.com',
281
+ mcp: agentAccess,
282
+ })
283
+ ```
284
+
285
+ `after-intro` preserves the title and introduction and puts Agent access
286
+ before the first content section. `end` places it at the end. Existing
287
+ markdown that already contains Agent access or a recognized server-card link
288
+ is preserved, so update a site's existing discovery section directly when
289
+ its URLs change. The optional catalog is an experimental discovery document,
290
+ not a requirement for using the MCP endpoint.
291
+
292
+ The writer applies these options to both files, whether Sonor generated the
293
+ content or local data supplied it. It resolves the origin from
294
+ `NEXT_PUBLIC_SITE_URL`, falling back to the `site` host. The handlers apply
295
+ explicit options even when serving an older file through `preferStatic`;
296
+ they use `baseUrl` or the configured site URL and never read the incoming
297
+ request. A CDN serving `public/llms.txt` directly still needs the build-time
298
+ writer to update that file. `mcp: false` disables automatic insertion; it
299
+ doesn't remove a site's existing discovery text.
300
+
232
301
  ### Step 5: On-Demand Revalidation (optional)
233
302
 
234
303
  When Sonor data changes (page summaries, FAQs, etc.), bust the ISR cache instantly instead of waiting for `s-maxage` to expire:
package/src/mcp/README.md CHANGED
@@ -9,7 +9,7 @@ definitions:
9
9
  | Surface | Who uses it | Entry point |
10
10
  |---|---|---|
11
11
  | Remote MCP endpoint (Streamable HTTP) | Off-browser agents — Claude, Cursor, any MCP client | `createMcpHandler` |
12
- | MCP Server Card (SEP-2127) | Crawlers and clients discovering the endpoint | `createMcpServerCardHandler` |
12
+ | Server card and experimental AI catalog | Crawlers and clients discovering the endpoint | `createMcpServerCardHandler`, `createMcpAiCatalogHandler` |
13
13
  | In-page WebMCP | Browser-driving agents | `<WebMcpTools>`, `declarativeToolForm` |
14
14
 
15
15
  One definition feeding all three is the point. The alternative — a tool list for
@@ -163,22 +163,45 @@ export const { POST, GET, DELETE, OPTIONS } = createMcpHandler({
163
163
  export const dynamic = 'force-dynamic'
164
164
  ```
165
165
 
166
- ### 3. Mount the card at BOTH well-known paths
166
+ ### 3. Mount the card and optional experimental catalog
167
+
168
+ The [ext-server-card discovery draft](https://github.com/modelcontextprotocol/ext-server-card/blob/main/docs/discovery.md)
169
+ is experimental. It recommends the card beside the endpoint at
170
+ `<streamable-http-url>/server-card` and a domain catalog at
171
+ `/.well-known/ai-catalog.json`. With the default endpoint, use
172
+ `/api/mcp/server-card` as the site's canonical card URL:
167
173
 
168
174
  ```ts
169
- // app/.well-known/mcp-server-card/route.ts ← canonical (SEP-2127)
170
- // app/.well-known/mcp.json/route.ts ← superseded SEP-1649, still probed
171
- import { createMcpServerCardHandler } from '@sonordev/site-kit/mcp'
175
+ // app/api/mcp/server-card/route.ts
176
+ import { createMcpServerCardHandler, MCP_SERVER_CARD_MEDIA_TYPE } from '@sonordev/site-kit/mcp'
172
177
  import { mcpServer } from '@/lib/mcp/server'
173
178
 
174
179
  export const { GET, OPTIONS } = createMcpServerCardHandler({
175
180
  info: mcpServer.info,
176
181
  tools: mcpServer.tools,
177
182
  baseUrl: 'https://example.com',
183
+ contentType: MCP_SERVER_CARD_MEDIA_TYPE, // application/mcp-server-card+json
184
+ })
185
+ ```
186
+
187
+ ```ts
188
+ // app/.well-known/ai-catalog.json/route.ts
189
+ import { createMcpAiCatalogHandler } from '@sonordev/site-kit/mcp'
190
+ import { mcpServer } from '@/lib/mcp/server'
191
+
192
+ export const { GET, OPTIONS } = createMcpAiCatalogHandler({
193
+ info: mcpServer.info,
194
+ baseUrl: 'https://example.com',
195
+ serverCardPath: '/api/mcp/server-card',
178
196
  })
179
- export const revalidate = 3600
180
197
  ```
181
198
 
199
+ The catalog returns `application/ai-catalog+json`. Both handlers use explicit
200
+ configuration and stay statically renderable without reading request data.
201
+ Keep existing `/.well-known/mcp-server-card` and `/.well-known/mcp.json`
202
+ aliases for clients that already use them. The card handler's default remains
203
+ `application/json`; set the vendor content type explicitly on the new path.
204
+
182
205
  ### 4. Register in-page (optional, for browser agents)
183
206
 
184
207
  ```tsx
@@ -188,10 +211,17 @@ export const revalidate = 3600
188
211
  ```
189
212
 
190
213
  Pass no tool list. The component checks for WebMCP support first and only then
191
- fetches `tools/list` from the endpoint — so an ordinary visitor does no work
192
- and the page carries no extra bytes, while an agent gets the same catalog the
193
- endpoint serves. Handing it descriptors from a server component instead would
194
- put the whole catalog in every page's RSC payload.
214
+ fetches `tools/list` from the endpoint. In a supported browser it starts when
215
+ the component mounts, without waiting for window load, an idle period, or a
216
+ human interaction. A browser without WebMCP makes no discovery request and
217
+ receives no catalog. Handing it descriptors from a server component instead
218
+ would put the whole catalog in every page's RSC payload.
219
+
220
+ `defer={true}` preserves the optional load + idle activation. Ordinary parent
221
+ renders keep the current registration; unmounting aborts discovery, remote
222
+ calls, and registrations that support the registration signal. If passing
223
+ `tools` or `localTools` explicitly, keep their arrays stable until the tools
224
+ change.
195
225
 
196
226
  ### 5. Rate-limit the public endpoint (Netlify)
197
227
 
@@ -268,8 +298,8 @@ is not re-exported from `@sonordev/site-kit/mcp`, which stays runtime-neutral.
268
298
 
269
299
  ### The card does not list tools — on purpose
270
300
 
271
- SEP-2127 deliberately omits primitives from the card: what a server exposes can
272
- vary with auth state and flags, so the authoritative list is whatever
301
+ The card's discovery shape omits primitives: what a server exposes can
302
+ vary with auth state and configuration, so the authoritative list is whatever
273
303
  `tools/list` returns at call time. A card that inlined tools would be a second
274
304
  source of truth that goes stale silently.
275
305
 
@@ -279,11 +309,15 @@ point and requires a reverse-DNS prefix, so the hint rides along without
279
309
  pretending to be standard — useful for crawlers that index the card and never
280
310
  connect.
281
311
 
282
- ### Two well-known paths
312
+ ### Experimental discovery and compatibility paths
283
313
 
284
- SEP-1649 proposed `/.well-known/mcp.json`; the ratified SEP-2127 moved to
285
- `/.well-known/mcp-server-card`. Deployed validators still probe the old path.
286
- Serving one document from two URLs costs nothing, so mount both.
314
+ Site-kit keeps `/.well-known/mcp-server-card` and `/.well-known/mcp.json`
315
+ for compatibility with existing integrations. The experimental
316
+ ext-server-card draft adds domain discovery through
317
+ `/.well-known/ai-catalog.json`, which links to the recommended endpoint-local
318
+ card at `/api/mcp/server-card`. These draft conventions aren't a guarantee
319
+ that every agent discovers or uses them. Keep the endpoint and existing card
320
+ URLs working while adding the catalog.
287
321
 
288
322
  ### Dual-era protocol support
289
323
 
@@ -1,8 +0,0 @@
1
- export { SitemapSync } from './chunk-GEXT7BTE.js';
2
- import './chunk-YVKRYQRG.js';
3
- import './chunk-43OCZ3JA.js';
4
- import './chunk-EKBEOXTH.js';
5
- import './chunk-D6ZC7XKZ.js';
6
- import './chunk-K4ZHAURD.js';
7
- import './chunk-F24FNCTK.js';
8
- import './chunk-PKBMQBKP.js';