nuxt-ai-ready 1.5.8 → 1.7.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 (123) hide show
  1. package/README.md +4 -1
  2. package/dist/cli.mjs +29 -37
  3. package/dist/devtools/lib/ai-ready/state.ts +4 -1
  4. package/dist/module.d.mts +32 -3
  5. package/dist/module.json +2 -2
  6. package/dist/module.mjs +1090 -82
  7. package/dist/runtime/app/composables/webmcp.d.ts +24 -0
  8. package/dist/runtime/app/composables/webmcp.js +103 -0
  9. package/dist/runtime/app/plugins/webmcp.client.d.ts +2 -0
  10. package/dist/runtime/app/plugins/webmcp.client.js +59 -0
  11. package/dist/runtime/app/webmcp-config.d.ts +3 -0
  12. package/dist/runtime/app/webmcp-config.js +7 -0
  13. package/dist/runtime/llms-txt-utils.d.ts +1 -1
  14. package/dist/runtime/llms-txt-utils.js +1 -1
  15. package/dist/runtime/mcp.d.ts +11 -5
  16. package/dist/runtime/mcp.js +2 -1
  17. package/dist/runtime/server/db/drizzle/client.d.ts +1 -1
  18. package/dist/runtime/server/db/drizzle/providers/bun.d.ts +1 -1
  19. package/dist/runtime/server/db/drizzle/providers/bun.js +1 -1
  20. package/dist/runtime/server/db/drizzle/providers/d1.d.ts +1 -1
  21. package/dist/runtime/server/db/drizzle/providers/d1.js +1 -1
  22. package/dist/runtime/server/db/drizzle/providers/dbPath.js +2 -1
  23. package/dist/runtime/server/db/drizzle/providers/libsql.d.ts +1 -1
  24. package/dist/runtime/server/db/drizzle/providers/libsql.js +1 -1
  25. package/dist/runtime/server/db/drizzle/providers/neon.d.ts +1 -1
  26. package/dist/runtime/server/db/drizzle/providers/neon.js +1 -1
  27. package/dist/runtime/server/db/drizzle/providers/sqlite.d.ts +1 -1
  28. package/dist/runtime/server/db/drizzle/providers/sqlite.js +1 -1
  29. package/dist/runtime/server/db/drizzle/queries.d.ts +1 -1
  30. package/dist/runtime/server/db/drizzle/queries.js +1 -1
  31. package/dist/runtime/server/db/drizzle/raw.d.ts +1 -1
  32. package/dist/runtime/server/db/queries.d.ts +5 -5
  33. package/dist/runtime/server/db/queries.js +1 -1
  34. package/dist/runtime/server/db/shared.js +10 -4
  35. package/dist/runtime/server/mcp/resources/pages.js +1 -1
  36. package/dist/runtime/server/mcp/tools/get-page-markdown.js +35 -0
  37. package/dist/runtime/server/mcp/tools/list-pages.js +12 -5
  38. package/dist/runtime/server/mcp/tools/search-pages.js +12 -5
  39. package/dist/runtime/server/middleware/markdown.d.ts +1 -1
  40. package/dist/runtime/server/middleware/markdown.js +40 -9
  41. package/dist/runtime/server/middleware/markdown.prerender.d.ts +1 -1
  42. package/dist/runtime/server/middleware/markdown.prerender.js +11 -5
  43. package/dist/runtime/server/plugins/db-lifecycle.d.ts +3 -1
  44. package/dist/runtime/server/plugins/html-capture.prerender.d.ts +3 -1
  45. package/dist/runtime/server/plugins/mcp-data.d.ts +10 -0
  46. package/dist/runtime/server/plugins/mcp-data.js +22 -0
  47. package/dist/runtime/server/plugins/sitemap-seeder.d.ts +3 -1
  48. package/dist/runtime/server/plugins/sitemap-seeder.js +1 -1
  49. package/dist/runtime/server/routes/__ai-ready/cron.get.d.ts +1 -1
  50. package/dist/runtime/server/routes/__ai-ready/cron.get.js +1 -1
  51. package/dist/runtime/server/routes/__ai-ready/devtools.get.d.ts +1 -1
  52. package/dist/runtime/server/routes/__ai-ready/devtools.get.js +2 -2
  53. package/dist/runtime/server/routes/__ai-ready/indexnow.post.d.ts +1 -1
  54. package/dist/runtime/server/routes/__ai-ready/indexnow.post.js +2 -2
  55. package/dist/runtime/server/routes/__ai-ready/pages.get.d.ts +6 -0
  56. package/dist/runtime/server/routes/__ai-ready/pages.get.js +48 -0
  57. package/dist/runtime/server/routes/__ai-ready/poll.post.d.ts +1 -7
  58. package/dist/runtime/server/routes/__ai-ready/poll.post.js +1 -1
  59. package/dist/runtime/server/routes/__ai-ready/prune.post.d.ts +1 -13
  60. package/dist/runtime/server/routes/__ai-ready/prune.post.js +2 -2
  61. package/dist/runtime/server/routes/__ai-ready/restore.post.d.ts +1 -4
  62. package/dist/runtime/server/routes/__ai-ready/restore.post.js +3 -3
  63. package/dist/runtime/server/routes/__ai-ready/status.get.d.ts +1 -1
  64. package/dist/runtime/server/routes/__ai-ready/status.get.js +2 -2
  65. package/dist/runtime/server/routes/__ai-ready-debug.get.d.ts +1 -103
  66. package/dist/runtime/server/routes/__ai-ready-debug.get.js +2 -2
  67. package/dist/runtime/server/routes/agent-skills-artifact.d.ts +2 -0
  68. package/dist/runtime/server/routes/agent-skills-artifact.js +19 -0
  69. package/dist/runtime/server/routes/agent-skills-index.d.ts +2 -0
  70. package/dist/runtime/server/routes/agent-skills-index.js +9 -0
  71. package/dist/runtime/server/routes/api-catalog.d.ts +4 -0
  72. package/dist/runtime/server/routes/api-catalog.js +13 -0
  73. package/dist/runtime/server/routes/indexnow-key.get.d.ts +1 -1
  74. package/dist/runtime/server/routes/indexnow-key.get.js +2 -2
  75. package/dist/runtime/server/routes/llms-full.txt.get.d.ts +1 -1
  76. package/dist/runtime/server/routes/llms-full.txt.get.js +2 -2
  77. package/dist/runtime/server/routes/llms.txt.get.d.ts +1 -1
  78. package/dist/runtime/server/routes/llms.txt.get.js +2 -2
  79. package/dist/runtime/server/routes/mcp-server-card.d.ts +3 -0
  80. package/dist/runtime/server/routes/mcp-server-card.js +20 -0
  81. package/dist/runtime/server/tasks/ai-ready-cron.d.ts +1 -1
  82. package/dist/runtime/server/tasks/ai-ready-cron.js +1 -1
  83. package/dist/runtime/server/utils/auth.d.ts +1 -1
  84. package/dist/runtime/server/utils/auth.js +2 -2
  85. package/dist/runtime/server/utils/batchIndex.d.ts +1 -1
  86. package/dist/runtime/server/utils/checkStale.d.ts +1 -1
  87. package/dist/runtime/server/utils/checkStale.js +1 -1
  88. package/dist/runtime/server/utils/cloudflare.d.ts +1 -1
  89. package/dist/runtime/server/utils/cloudflare.js +9 -6
  90. package/dist/runtime/server/utils/content-negotiation.d.ts +23 -0
  91. package/dist/runtime/server/utils/content-negotiation.js +23 -0
  92. package/dist/runtime/server/utils/content.d.ts +1 -1
  93. package/dist/runtime/server/utils/context.d.ts +1 -1
  94. package/dist/runtime/server/utils/context.js +1 -1
  95. package/dist/runtime/server/utils/fetch.d.ts +3 -0
  96. package/dist/runtime/server/utils/fetch.js +10 -0
  97. package/dist/runtime/server/utils/indexPage.d.ts +1 -1
  98. package/dist/runtime/server/utils/indexPage.js +6 -4
  99. package/dist/runtime/server/utils/indexnow.d.ts +1 -1
  100. package/dist/runtime/server/utils/indexnow.js +1 -1
  101. package/dist/runtime/server/utils/link-header.js +3 -0
  102. package/dist/runtime/server/utils/llms-full.js +18 -25
  103. package/dist/runtime/server/utils/runCron.d.ts +1 -1
  104. package/dist/runtime/server/utils/runCron.js +1 -1
  105. package/dist/runtime/server/utils/sitemap.d.ts +3 -3
  106. package/dist/runtime/server/utils/sitemap.js +271 -80
  107. package/dist/runtime/server/utils.d.ts +8 -2
  108. package/dist/runtime/server/utils.js +6 -5
  109. package/dist/runtime/site-tool-catalog.d.ts +31 -0
  110. package/dist/runtime/site-tool-catalog.js +52 -0
  111. package/dist/runtime/site-tool-config.d.ts +75 -0
  112. package/dist/runtime/site-tool-config.js +0 -0
  113. package/dist/runtime/types.d.ts +142 -1
  114. package/dist/runtime/webmcp-public.d.ts +4 -0
  115. package/dist/runtime/webmcp-public.js +3 -0
  116. package/dist/runtime/webmcp-site-tools.d.ts +26 -0
  117. package/dist/runtime/webmcp-site-tools.js +282 -0
  118. package/dist/runtime/webmcp.d.ts +163 -0
  119. package/dist/runtime/webmcp.js +59 -0
  120. package/dist/types.d.mts +4 -2
  121. package/mcp.d.ts +1 -1
  122. package/package.json +42 -32
  123. package/webmcp.d.ts +1 -0
package/README.md CHANGED
@@ -21,7 +21,10 @@ Nuxt AI Ready implements both. It converts your pages to markdown, generates llm
21
21
  - 📝 **[Nuxt Content](https://content.nuxt.com) Integration**: Routes backed by a page collection serve source markdown directly, skipping HTML→markdown conversion
22
22
  - 📡 **Content Signals**: Configure AI training/search/input permissions via [Nuxt Robots](https://nuxtseo.com/robots)
23
23
  - 🌐 **Sitemap Integration**: Index AI-allowed pages via [Nuxt Sitemap](https://nuxtseo.com/sitemap)
24
- - ⚡ **MCP Server**: `list_pages` and `search_pages` tools with FTS5 full-text search
24
+ - ⚡ **MCP Server**: List, search and read indexed pages through `@nuxtjs/mcp-toolkit`
25
+ - 🔎 **[API Catalog](https://nuxtseo.com/ai-ready/guides/api-catalog)**: Publish RFC 9727 API discovery metadata and advertise it through `Link` headers
26
+ - 🧠 **Agent Skills**: Publish verified local or external skills through the v0.2.0 discovery index
27
+ - 🧩 **[WebMCP](https://nuxtseo.com/ai-ready/guides/webmcp)**: Give browser agents access to built-in site tools or your own tools with `useWebMcpTool()`
25
28
  - 🗄️ **Runtime Indexing**: Index pages on-demand without prerendering, with SQLite/D1/LibSQL support
26
29
  - 🔔 **[IndexNow](https://nuxtseo.com/ai-ready/guides/indexnow)**: Instantly notify Bing, Yandex, and other search engines when pages change
27
30
  - 🌏 **[i18n Aware](https://nuxtseo.com/ai-ready/guides/i18n)**: Auto-detects [`@nuxtjs/i18n`](https://i18n.nuxtjs.org/) for hreflang `Link` headers, locale-tagged frontmatter, and an Available Languages section in `llms.txt`
package/dist/cli.mjs CHANGED
@@ -12,11 +12,26 @@ async function getSecret(cwd) {
12
12
  if (!existsSync(secretPath)) {
13
13
  return null;
14
14
  }
15
- return fsp.readFile(secretPath, "utf-8").then((s) => s.trim()).catch(() => null);
15
+ return fsp.readFile(secretPath, "utf-8").then((s) => s.trim()).catch(() => {
16
+ return null;
17
+ });
16
18
  }
17
19
  function authHeaders(secret) {
18
20
  return { Authorization: `Bearer ${secret}` };
19
21
  }
22
+ async function requireSecret(cwd, hint = "") {
23
+ const secret = await getSecret(cwd);
24
+ if (!secret) {
25
+ consola.error(`No secret found. Run \`nuxi dev\` or \`nuxi build\` first${hint}.`);
26
+ }
27
+ return secret;
28
+ }
29
+ async function fetchJson(url, init, errorLabel = "Failed") {
30
+ return fetch(url, init).then((r) => r.json()).catch((err) => {
31
+ consola.error(`${errorLabel}: ${err.message}`);
32
+ return null;
33
+ });
34
+ }
20
35
  const main = defineCommand({
21
36
  meta: {
22
37
  name: "nuxt-ai-ready",
@@ -44,17 +59,12 @@ const main = defineCommand({
44
59
  },
45
60
  async run({ args }) {
46
61
  const cwd = resolve(args.cwd || ".");
47
- const secret = await getSecret(cwd);
48
- if (!secret) {
49
- consola.error("No secret found. Run `nuxi dev` or `nuxi build` first to generate one.");
62
+ const secret = await requireSecret(cwd, " to generate one");
63
+ if (!secret)
50
64
  return;
51
- }
52
65
  const url = `${args.url}/__ai-ready/status`;
53
66
  consola.info(`Fetching status from ${args.url}...`);
54
- const res = await fetch(url, { headers: authHeaders(secret) }).then((r) => r.json()).catch((err) => {
55
- consola.error(`Failed to connect: ${err.message}`);
56
- return null;
57
- });
67
+ const res = await fetchJson(url, { headers: authHeaders(secret) }, "Failed to connect");
58
68
  if (!res)
59
69
  return;
60
70
  consola.box("AI Ready Status");
@@ -146,11 +156,9 @@ const main = defineCommand({
146
156
  },
147
157
  async run({ args }) {
148
158
  const cwd = resolve(args.cwd || ".");
149
- const secret = await getSecret(cwd);
150
- if (!secret) {
151
- consola.error("No secret found. Run `nuxi dev` or `nuxi build` first.");
159
+ const secret = await requireSecret(cwd);
160
+ if (!secret)
152
161
  return;
153
- }
154
162
  const params = new URLSearchParams();
155
163
  if (args.all) {
156
164
  params.set("all", "true");
@@ -159,10 +167,7 @@ const main = defineCommand({
159
167
  }
160
168
  const url = `${args.url}/__ai-ready/poll?${params}`;
161
169
  consola.info(`Triggering poll at ${args.url}...`);
162
- const res = await fetch(url, { method: "POST", headers: authHeaders(secret) }).then((r) => r.json()).catch((err) => {
163
- consola.error(`Failed: ${err.message}`);
164
- return null;
165
- });
170
+ const res = await fetchJson(url, { method: "POST", headers: authHeaders(secret) });
166
171
  if (!res)
167
172
  return;
168
173
  consola.success(`Indexed: ${colors.green(res.indexed?.toString() || "0")} pages`);
@@ -201,21 +206,16 @@ const main = defineCommand({
201
206
  },
202
207
  async run({ args }) {
203
208
  const cwd = resolve(args.cwd || ".");
204
- const secret = await getSecret(cwd);
205
- if (!secret) {
206
- consola.error("No secret found. Run `nuxi dev` or `nuxi build` first.");
209
+ const secret = await requireSecret(cwd);
210
+ if (!secret)
207
211
  return;
208
- }
209
212
  const params = new URLSearchParams();
210
213
  if (!args.clear) {
211
214
  params.set("clear", "false");
212
215
  }
213
216
  const url = `${args.url}/__ai-ready/restore?${params}`;
214
217
  consola.info(`Restoring database at ${args.url}...`);
215
- const res = await fetch(url, { method: "POST", headers: authHeaders(secret) }).then((r) => r.json()).catch((err) => {
216
- consola.error(`Failed: ${err.message}`);
217
- return null;
218
- });
218
+ const res = await fetchJson(url, { method: "POST", headers: authHeaders(secret) });
219
219
  if (!res)
220
220
  return;
221
221
  consola.success(`Restored: ${colors.green(res.restored?.toString() || "0")} pages`);
@@ -265,12 +265,9 @@ const main = defineCommand({
265
265
  params.set("ttl", args.ttl);
266
266
  const url = `${args.url}/__ai-ready/prune?${params}`;
267
267
  consola.info(`${args.dry ? "Previewing" : "Pruning"} stale routes at ${args.url}...`);
268
- const res = await fetch(url, {
268
+ const res = await fetchJson(url, {
269
269
  method: "POST",
270
270
  headers: secret ? authHeaders(secret) : void 0
271
- }).then((r) => r.json()).catch((err) => {
272
- consola.error(`Failed: ${err.message}`);
273
- return null;
274
271
  });
275
272
  if (!res)
276
273
  return;
@@ -315,20 +312,15 @@ const main = defineCommand({
315
312
  },
316
313
  async run({ args }) {
317
314
  const cwd = resolve(args.cwd || ".");
318
- const secret = await getSecret(cwd);
319
- if (!secret) {
320
- consola.error("No secret found. Run `nuxi dev` or `nuxi build` first.");
315
+ const secret = await requireSecret(cwd);
316
+ if (!secret)
321
317
  return;
322
- }
323
318
  const params = new URLSearchParams({
324
319
  limit: args.limit || "100"
325
320
  });
326
321
  const url = `${args.url}/__ai-ready/indexnow?${params}`;
327
322
  consola.info(`Triggering IndexNow sync at ${args.url}...`);
328
- const res = await fetch(url, { method: "POST", headers: authHeaders(secret) }).then((r) => r.json()).catch((err) => {
329
- consola.error(`Failed: ${err.message}`);
330
- return null;
331
- });
323
+ const res = await fetchJson(url, { method: "POST", headers: authHeaders(secret) });
332
324
  if (!res)
333
325
  return;
334
326
  if (res.success) {
@@ -9,7 +9,10 @@ export const loading = ref(true)
9
9
  export async function refreshSources() {
10
10
  if (!appFetch.value || typeof appFetch.value !== 'function')
11
11
  return
12
- data.value = await appFetch.value('/__ai-ready__/debug.json', { responseType: 'json' }).catch(() => null)
12
+ data.value = await appFetch.value('/__ai-ready__/debug.json', { responseType: 'json' }).catch(() => {
13
+ // The devtools host can disconnect while a refresh is in flight.
14
+ return null
15
+ })
13
16
  loading.value = false
14
17
  if (data.value?.siteConfigUrl)
15
18
  productionUrl.value = data.value.siteConfigUrl
package/dist/module.d.mts CHANGED
@@ -1,6 +1,8 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { LlmsTxtConfig, ModuleOptions } from '../dist/runtime/types.js';
3
- export { ModuleOptions } from '../dist/runtime/types.js';
2
+ import { LlmsTxtConfig, ContentNegotiationPolicy, ModuleOptions } from '../dist/runtime/types.js';
3
+ export { AgentSkillConfig, AgentSkillsConfig, AgentSkillsIndex, AgentSkillsIndexEntry, ApiCatalogConfig, ApiCatalogEntry, ApiCatalogLinkTarget, ApiCatalogLinks, ExternalAgentSkillConfig, LocalAgentSkillConfig, McpServerCardConfig, ModuleOptions } from '../dist/runtime/types.js';
4
+ import { ResolvedWebMcpToolsConfig } from '../dist/runtime/site-tool-config.js';
5
+ export { GetPageMarkdownToolOptions, ListPagesToolOptions, McpSiteToolAttachmentOptions, SearchPagesToolOptions, SiteToolOptions, SiteToolsConfig, WebMcpSiteToolAttachmentOptions } from '../dist/runtime/site-tool-config.js';
4
6
 
5
7
  interface ParsedMarkdownResult {
6
8
  markdown: string;
@@ -11,6 +13,27 @@ interface ParsedMarkdownResult {
11
13
  updatedAt?: string;
12
14
  }
13
15
 
16
+ interface ResolvedApiCatalogLinkTarget {
17
+ href: string;
18
+ type?: string;
19
+ title?: string;
20
+ hreflang?: string[];
21
+ media?: string;
22
+ }
23
+ type ResolvedApiCatalogLinksetEntry = Record<string, string | ResolvedApiCatalogLinkTarget[]>;
24
+ interface ResolvedApiCatalogConfig {
25
+ href: string;
26
+ mediaType: string;
27
+ document: {
28
+ linkset: ResolvedApiCatalogLinksetEntry[];
29
+ };
30
+ }
31
+
32
+ interface ResolvedWebMcpConfig {
33
+ tools: ResolvedWebMcpToolsConfig;
34
+ exposedTo?: string[];
35
+ }
36
+
14
37
  interface ModuleHooks {
15
38
  /**
16
39
  * Hook called when page markdown is generated during prerendering.
@@ -36,6 +59,7 @@ declare module '@nuxt/schema' {
36
59
  interface ModulePublicRuntimeConfig {
37
60
  debug: boolean;
38
61
  debugCron: boolean;
62
+ contentNegotiation: ContentNegotiationPolicy;
39
63
  version: string;
40
64
  mdreamOptions: ModuleOptions['mdreamOptions'];
41
65
  markdownCacheHeaders: Required<NonNullable<ModuleOptions['markdownCacheHeaders']>>;
@@ -66,8 +90,13 @@ interface ModulePublicRuntimeConfig {
66
90
  }>;
67
91
  } | null;
68
92
  ftsTokenizer?: string;
93
+ apiCatalog?: ResolvedApiCatalogConfig;
94
+ }
95
+ /** Runtime config exposed to the browser, only set when WebMCP is enabled. */
96
+ interface ModuleAppRuntimeConfig {
97
+ webmcp: ResolvedWebMcpConfig;
69
98
  }
70
99
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
71
100
 
72
101
  export { _default as default };
73
- export type { ModuleHooks, ModulePublicRuntimeConfig };
102
+ export type { ModuleAppRuntimeConfig, ModuleHooks, ModulePublicRuntimeConfig };
package/dist/module.json CHANGED
@@ -4,9 +4,9 @@
4
4
  "nuxt": ">=4.0.0"
5
5
  },
6
6
  "configKey": "aiReady",
7
- "version": "1.5.8",
7
+ "version": "1.7.0",
8
8
  "builder": {
9
- "@nuxt/module-builder": "1.0.2",
9
+ "@nuxt/module-builder": "1.0.3",
10
10
  "unbuild": "3.6.1"
11
11
  }
12
12
  }