nuxt-ai-ready 1.5.7 β†’ 1.6.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 (47) hide show
  1. package/README.md +2 -1
  2. package/dist/cli.mjs +26 -36
  3. package/dist/module.d.mts +14 -2
  4. package/dist/module.json +2 -2
  5. package/dist/module.mjs +304 -38
  6. package/dist/runtime/app/composables/webmcp.d.ts +24 -0
  7. package/dist/runtime/app/composables/webmcp.js +103 -0
  8. package/dist/runtime/app/plugins/webmcp.client.d.ts +2 -0
  9. package/dist/runtime/app/plugins/webmcp.client.js +59 -0
  10. package/dist/runtime/app/webmcp-config.d.ts +3 -0
  11. package/dist/runtime/app/webmcp-config.js +7 -0
  12. package/dist/runtime/llms-txt-utils.js +34 -2
  13. package/dist/runtime/mcp.d.ts +11 -5
  14. package/dist/runtime/mcp.js +2 -1
  15. package/dist/runtime/server/db/queries.d.ts +4 -4
  16. package/dist/runtime/server/mcp/tools/get-page-markdown.js +35 -0
  17. package/dist/runtime/server/mcp/tools/list-pages.js +11 -4
  18. package/dist/runtime/server/mcp/tools/search-pages.js +11 -4
  19. package/dist/runtime/server/middleware/markdown.js +35 -8
  20. package/dist/runtime/server/middleware/markdown.prerender.js +1 -1
  21. package/dist/runtime/server/plugins/mcp-data.d.ts +2 -0
  22. package/dist/runtime/server/plugins/mcp-data.js +22 -0
  23. package/dist/runtime/server/routes/__ai-ready/pages.get.d.ts +41 -0
  24. package/dist/runtime/server/routes/__ai-ready/pages.get.js +48 -0
  25. package/dist/runtime/server/utils/cloudflare.js +9 -6
  26. package/dist/runtime/server/utils/content-negotiation.d.ts +16 -0
  27. package/dist/runtime/server/utils/content-negotiation.js +23 -0
  28. package/dist/runtime/server/utils/llms-full.js +18 -25
  29. package/dist/runtime/server/utils/sitemap.d.ts +2 -2
  30. package/dist/runtime/server/utils/sitemap.js +269 -79
  31. package/dist/runtime/server/utils.d.ts +7 -1
  32. package/dist/runtime/server/utils.js +4 -3
  33. package/dist/runtime/site-tool-catalog.d.ts +31 -0
  34. package/dist/runtime/site-tool-catalog.js +52 -0
  35. package/dist/runtime/site-tool-config.d.ts +75 -0
  36. package/dist/runtime/site-tool-config.js +0 -0
  37. package/dist/runtime/types.d.ts +44 -1
  38. package/dist/runtime/webmcp-public.d.ts +4 -0
  39. package/dist/runtime/webmcp-public.js +3 -0
  40. package/dist/runtime/webmcp-site-tools.d.ts +26 -0
  41. package/dist/runtime/webmcp-site-tools.js +282 -0
  42. package/dist/runtime/webmcp.d.ts +163 -0
  43. package/dist/runtime/webmcp.js +59 -0
  44. package/dist/types.d.mts +3 -1
  45. package/mcp.d.ts +1 -1
  46. package/package.json +33 -27
  47. package/webmcp.d.ts +1 -0
package/README.md CHANGED
@@ -21,7 +21,8 @@ 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
+ - 🧩 **[WebMCP](https://nuxtseo.com/ai-ready/guides/webmcp)**: Give browser agents access to built-in site tools or your own tools with `useWebMcpTool()`
25
26
  - πŸ—„οΈ **Runtime Indexing**: Index pages on-demand without prerendering, with SQLite/D1/LibSQL support
26
27
  - πŸ”” **[IndexNow](https://nuxtseo.com/ai-ready/guides/indexnow)**: Instantly notify Bing, Yandex, and other search engines when pages change
27
28
  - 🌏 **[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
@@ -17,6 +17,19 @@ async function getSecret(cwd) {
17
17
  function authHeaders(secret) {
18
18
  return { Authorization: `Bearer ${secret}` };
19
19
  }
20
+ async function requireSecret(cwd, hint = "") {
21
+ const secret = await getSecret(cwd);
22
+ if (!secret) {
23
+ consola.error(`No secret found. Run \`nuxi dev\` or \`nuxi build\` first${hint}.`);
24
+ }
25
+ return secret;
26
+ }
27
+ async function fetchJson(url, init, errorLabel = "Failed") {
28
+ return fetch(url, init).then((r) => r.json()).catch((err) => {
29
+ consola.error(`${errorLabel}: ${err.message}`);
30
+ return null;
31
+ });
32
+ }
20
33
  const main = defineCommand({
21
34
  meta: {
22
35
  name: "nuxt-ai-ready",
@@ -44,17 +57,12 @@ const main = defineCommand({
44
57
  },
45
58
  async run({ args }) {
46
59
  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.");
60
+ const secret = await requireSecret(cwd, " to generate one");
61
+ if (!secret)
50
62
  return;
51
- }
52
63
  const url = `${args.url}/__ai-ready/status`;
53
64
  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
- });
65
+ const res = await fetchJson(url, { headers: authHeaders(secret) }, "Failed to connect");
58
66
  if (!res)
59
67
  return;
60
68
  consola.box("AI Ready Status");
@@ -146,11 +154,9 @@ const main = defineCommand({
146
154
  },
147
155
  async run({ args }) {
148
156
  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.");
157
+ const secret = await requireSecret(cwd);
158
+ if (!secret)
152
159
  return;
153
- }
154
160
  const params = new URLSearchParams();
155
161
  if (args.all) {
156
162
  params.set("all", "true");
@@ -159,10 +165,7 @@ const main = defineCommand({
159
165
  }
160
166
  const url = `${args.url}/__ai-ready/poll?${params}`;
161
167
  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
- });
168
+ const res = await fetchJson(url, { method: "POST", headers: authHeaders(secret) });
166
169
  if (!res)
167
170
  return;
168
171
  consola.success(`Indexed: ${colors.green(res.indexed?.toString() || "0")} pages`);
@@ -201,21 +204,16 @@ const main = defineCommand({
201
204
  },
202
205
  async run({ args }) {
203
206
  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.");
207
+ const secret = await requireSecret(cwd);
208
+ if (!secret)
207
209
  return;
208
- }
209
210
  const params = new URLSearchParams();
210
211
  if (!args.clear) {
211
212
  params.set("clear", "false");
212
213
  }
213
214
  const url = `${args.url}/__ai-ready/restore?${params}`;
214
215
  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
- });
216
+ const res = await fetchJson(url, { method: "POST", headers: authHeaders(secret) });
219
217
  if (!res)
220
218
  return;
221
219
  consola.success(`Restored: ${colors.green(res.restored?.toString() || "0")} pages`);
@@ -265,12 +263,9 @@ const main = defineCommand({
265
263
  params.set("ttl", args.ttl);
266
264
  const url = `${args.url}/__ai-ready/prune?${params}`;
267
265
  consola.info(`${args.dry ? "Previewing" : "Pruning"} stale routes at ${args.url}...`);
268
- const res = await fetch(url, {
266
+ const res = await fetchJson(url, {
269
267
  method: "POST",
270
268
  headers: secret ? authHeaders(secret) : void 0
271
- }).then((r) => r.json()).catch((err) => {
272
- consola.error(`Failed: ${err.message}`);
273
- return null;
274
269
  });
275
270
  if (!res)
276
271
  return;
@@ -315,20 +310,15 @@ const main = defineCommand({
315
310
  },
316
311
  async run({ args }) {
317
312
  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.");
313
+ const secret = await requireSecret(cwd);
314
+ if (!secret)
321
315
  return;
322
- }
323
316
  const params = new URLSearchParams({
324
317
  limit: args.limit || "100"
325
318
  });
326
319
  const url = `${args.url}/__ai-ready/indexnow?${params}`;
327
320
  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
- });
321
+ const res = await fetchJson(url, { method: "POST", headers: authHeaders(secret) });
332
322
  if (!res)
333
323
  return;
334
324
  if (res.success) {
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';
2
+ import { LlmsTxtConfig, ContentNegotiationPolicy, ModuleOptions } from '../dist/runtime/types.js';
3
3
  export { 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,11 @@ interface ParsedMarkdownResult {
11
13
  updatedAt?: string;
12
14
  }
13
15
 
16
+ interface ResolvedWebMcpConfig {
17
+ tools: ResolvedWebMcpToolsConfig;
18
+ exposedTo?: string[];
19
+ }
20
+
14
21
  interface ModuleHooks {
15
22
  /**
16
23
  * Hook called when page markdown is generated during prerendering.
@@ -36,6 +43,7 @@ declare module '@nuxt/schema' {
36
43
  interface ModulePublicRuntimeConfig {
37
44
  debug: boolean;
38
45
  debugCron: boolean;
46
+ contentNegotiation: ContentNegotiationPolicy;
39
47
  version: string;
40
48
  mdreamOptions: ModuleOptions['mdreamOptions'];
41
49
  markdownCacheHeaders: Required<NonNullable<ModuleOptions['markdownCacheHeaders']>>;
@@ -67,7 +75,11 @@ interface ModulePublicRuntimeConfig {
67
75
  } | null;
68
76
  ftsTokenizer?: string;
69
77
  }
78
+ /** Runtime config exposed to the browser, only set when WebMCP is enabled. */
79
+ interface ModuleAppRuntimeConfig {
80
+ webmcp: ResolvedWebMcpConfig;
81
+ }
70
82
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
71
83
 
72
84
  export { _default as default };
73
- export type { ModuleHooks, ModulePublicRuntimeConfig };
85
+ 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.7",
7
+ "version": "1.6.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
  }