diff --git a/src/components/docs/RateLimits.astro b/src/components/docs/RateLimits.astro
index b0e9fa2..e037154 100644
--- a/src/components/docs/RateLimits.astro
+++ b/src/components/docs/RateLimits.astro
@@ -1,15 +1,20 @@
---
import { env } from 'cloudflare:workers';
import {
+ effectiveLimitNote,
formatTokens,
- getRateLimitsConfig,
+ imageModelNote,
+ modelRateLabel,
windowedModelBody,
windowedModelHeadline,
rateLimitsLabels,
} from '../../lib/rateLimits';
+import { resolveRateLimitsConfig } from '../../lib/limitsPolicy';
-const { perKey, tokensPerMinuteByModel, requestsPerMinuteByModel, windowedModels } =
- getRateLimitsConfig(env);
+// Awaited, not called: with LIMITS_POLICY_URL unset this resolves to the
+// built-in table without making a request. See src/lib/limitsPolicy.ts.
+const { perKey, tokensPerMinuteByModel, exemptModels, windowedModels, imageModels } =
+ await resolveRateLimitsConfig(env);
// This card is embedded from both the English and the Spanish guides, and MDX
// content cannot pass props down from the layout, so the locale is read off the
@@ -60,6 +65,10 @@ const T = rateLimitsLabels(lang);
+{
+ /* Published as a list rather than left out. An endpoint missing from the
+ table above cannot be told apart from one we forgot to measure, which is
+ how `rerank` came to sit here with an invented 1000 rpm for months. */
+}
+
+
+{
+ /* Image generation is served by cloud-api against Workers AI, not through
+ LiteLLM, so none of the limits above reach it. Its own block rather than a
+ row, because the first thing to say about it is that the key's limits do
+ not apply - which no row can say. */
+}
+{
+ imageModels.map((m) => (
+
+
+ {m.model} · {T.images}
+
+
+
+
{T.perSecond}
+
{m.requestsPerSecond}
+
+
+
{T.burst}
+
{m.burst}
+
+
+
{T.monthlyRequests}
+
{m.monthlyRequests}
+
+
+
{T.maxVariants}
+
{m.maxVariants}
+
+
+
+ {imageModelNote(m, lang)}
+
+
+ ))
+}
diff --git a/src/content/docs-es/agent-setup.mdx b/src/content/docs-es/agent-setup.mdx
index edc1c00..d7e0266 100644
--- a/src/content/docs-es/agent-setup.mdx
+++ b/src/content/docs-es/agent-setup.mdx
@@ -119,7 +119,7 @@ Cada página de esta sección tiene la misma forma: qué necesitas, la configura
name: 'Servidor MCP',
href: '/es/docs/mcp',
kind: 'Herramientas',
- note: 'La búsqueda web de NaN dentro de cualquier agente compatible con MCP.',
+ note: 'Deprecado. La búsqueda web de NaN dentro de cualquier agente compatible con MCP, y se retira con ella.',
},
]}
/>
diff --git a/src/content/docs-es/agents.md b/src/content/docs-es/agents.md
index 54655ce..e595ef8 100644
--- a/src/content/docs-es/agents.md
+++ b/src/content/docs-es/agents.md
@@ -10,7 +10,7 @@ group: Guías
NaN Cloud te permite desplegar agentes de IA en tu propia **microVM**: una máquina virtual ligera con QEMU y KVM, con su propio kernel, su propio sistema de ficheros y acceso root completo. Aislada del host y del resto de miembros. El primer tipo de agente disponible es **Hermes**.
> **¿Usas un agente que alojas tú?**
-> Si ejecutas tu propio agente compatible con MCP en otro sitio, puedes enchufarle nuestras herramientas (como la búsqueda web) directamente, con la misma API key, a través de nuestro [servidor MCP](/es/docs/api#tag/mcp) remoto.
+> Si ejecutas tu propio agente compatible con MCP en otro sitio, puedes enchufarle nuestras herramientas (como la búsqueda web) directamente, con la misma API key, a través de nuestro [servidor MCP](/es/docs/api#tag/mcp) remoto. Ojo: el servidor MCP y la búsqueda web están **deprecados** y se van a retirar.
## Arquitectura
diff --git a/src/content/docs-es/claude-code.mdx b/src/content/docs-es/claude-code.mdx
index 48699d3..fa0d15a 100644
--- a/src/content/docs-es/claude-code.mdx
+++ b/src/content/docs-es/claude-code.mdx
@@ -201,4 +201,4 @@ En cualquiera de los dos, evita `glm5.3` para tareas que impliquen leer capturas
## Las herramientas de NaN, aparte
-Independientemente del camino que elijas, puedes darle a Claude Code la búsqueda web del clúster con una sola orden. Está en [Servidor MCP](/es/docs/mcp).
+Independientemente del camino que elijas, puedes darle a Claude Code la búsqueda web del clúster con una sola orden. Está en [Servidor MCP](/es/docs/mcp), que está **deprecado**: hoy sigue funcionando, pero se retira junto con la búsqueda web, así que no construyas encima.
diff --git a/src/content/docs-es/examples.md b/src/content/docs-es/examples.md
index 5a06d90..920b6f7 100644
--- a/src/content/docs-es/examples.md
+++ b/src/content/docs-es/examples.md
@@ -187,7 +187,7 @@ for r in response["results"]:
print(f"{r['index']}: {r['relevance_score']:.3f}")
```
-También funciona con `requests` a pelo o con cualquier cliente HTTP: el endpoint es compatible con OpenAI tanto en la autenticación como en el formato del cuerpo.
+También funciona con `requests` a pelo o con cualquier cliente HTTP: manda el cuerpo JSON con tu key en el Bearer. `/rerank` es un endpoint nuestro, no está en la especificación de OpenAI: la autenticación es la misma, el cuerpo es nuestro.
## model: kokoro
@@ -472,10 +472,12 @@ console.log(image.data[0].url);
`/images/edits` acepta hasta cuatro imágenes de referencia (PNG, JPEG o WebP, de menos de 25 MB cada una) y no admite `mask`: mandar una devuelve `400`.
-Las imágenes necesitan membresía de inferencia, `403` si no la tienes, y van por su propio presupuesto: 20 peticiones por minuto y 100 al mes, que no toca tu cuota de tokens.
+Las imágenes necesitan membresía de inferencia, `403` si no la tienes, y van por su propio presupuesto, que ni toca tu cuota de tokens ni es el de tu key: la generación de imágenes no pasa por la API de inferencia compartida. Una petición por segundo con una ráfaga de 3, y 100 peticiones por mes natural. Una petición que pida varias imágenes sigue costando una.
## tool: web search
+**Deprecado.** La búsqueda web se retira, tanto por este endpoint como por el [servidor MCP](/es/docs/mcp). Hoy sigue funcionando y anunciaremos una fecha antes de que deje de hacerlo, pero no construyas nada nuevo encima.
+
búsqueda web autenticada para agentes: `POST /v1/search`
### curl
diff --git a/src/content/docs-es/gentle-ai.mdx b/src/content/docs-es/gentle-ai.mdx
index 640e652..ecc9fdc 100644
--- a/src/content/docs-es/gentle-ai.mdx
+++ b/src/content/docs-es/gentle-ai.mdx
@@ -131,5 +131,5 @@ Conviene pasar `sync` después de cada `upgrade`: lo primero actualiza el progra
## Siguientes pasos
- [Configurar tu agente](/es/docs/agent-setup): conecta primero tu herramienta al clúster.
-- [Servidor MCP](/es/docs/mcp): añade además la búsqueda web de NaN a tu agente.
+- [Servidor MCP](/es/docs/mcp): añade además la búsqueda web de NaN a tu agente. **Deprecado**, se retira junto con la búsqueda web.
- [Elige tu modelo](/es/docs/choose-a-model): qué modelo pedir para cada tarea.
diff --git a/src/content/docs-es/getting-started.mdx b/src/content/docs-es/getting-started.mdx
index 7e16d23..22a385a 100644
--- a/src/content/docs-es/getting-started.mdx
+++ b/src/content/docs-es/getting-started.mdx
@@ -153,7 +153,7 @@ El detalle completo, endpoint a endpoint, está en la [referencia de la API](/es
Dos límites van por API key y se aplican a todo lo que llames: peticiones por minuto y peticiones a la vez.
-Encima de esos, algunos modelos llevan el suyo: un techo de tokens por minuto en los modelos de chat grandes, y uno de peticiones por minuto en `rerank`. `glm5.3` no se rige por minuto en absoluto, sino por una ventana móvil de tokens más una asignación por periodo de facturación. La búsqueda web va por un presupuesto separado del de los modelos.
+Encima de esos, cada modelo de chat lleva su propio techo de tokens por minuto, y no son el mismo número: cada uno es el contexto de ese modelo por las veces que puedes rellenarlo en un minuto. Los endpoints que no son de chat, `rerank`, `qwen3-embedding`, `kokoro` y `whisper`, no llevan techo propio, lo que no los hace gratis: los 60 por minuto de tu key los siguen contando. `glm5.3` tiene techo como los demás, pero lo que de verdad lo limita es una ventana móvil de tokens más una asignación por periodo de facturación. La búsqueda web va por un presupuesto separado del de los modelos.
Las cifras vigentes están al final de [Modelos](/es/docs/models), que es donde se publican para que no haya dos versiones de la misma cifra dando vueltas.
diff --git a/src/content/docs-es/intro.md b/src/content/docs-es/intro.md
index 2e916cc..2acc8a4 100644
--- a/src/content/docs-es/intro.md
+++ b/src/content/docs-es/intro.md
@@ -28,7 +28,7 @@ Los límites van por API key — un tope de peticiones por minuto y un máximo d
- [Elige tu modelo](/es/docs/choose-a-model): qué modelo pedir para cada tarea y cómo se escribe su id.
- [Configurar tu agente](/es/docs/agent-setup): Claude Code, Codex, Cursor, Cline, OpenCode, Zed y compañía.
- [CLI de NaN](/es/docs/nan-cli): la herramienta oficial de terminal, que además configura varias de ellas por ti.
-- [Servidor MCP](/es/docs/mcp): la búsqueda web de NaN dentro de tu agente.
+- [Servidor MCP](/es/docs/mcp): la búsqueda web de NaN dentro de tu agente. **Deprecado**, se retira junto con la búsqueda web.
- [Referencia de la API](/es/docs/api): todos los endpoints, campo a campo.
- [Modelos](/es/docs/models): las fichas técnicas y los límites.
- [Ejemplos](/es/docs/examples): fragmentos en Python, Node.js y curl.
diff --git a/src/content/docs-es/mcp.mdx b/src/content/docs-es/mcp.mdx
index e8f3a39..b2c001e 100644
--- a/src/content/docs-es/mcp.mdx
+++ b/src/content/docs-es/mcp.mdx
@@ -1,17 +1,24 @@
---
title: Servidor MCP
-description: Enchufa la búsqueda web de NaN en cualquier agente compatible con MCP.
+description: "Deprecado: la búsqueda web de NaN dentro de cualquier agente compatible con MCP. Se retira junto con la búsqueda web."
order: 16
group: Configurar tu agente
---
import Details from '../../components/docs/Details.astro';
+import Callout from '../../components/docs/Callout.astro';
# Servidor MCP.
+
+La búsqueda web se va, tanto por API como por este servidor, y la búsqueda web es la única herramienta que este servidor tiene. Así que el servidor MCP se va con ella.
+
+Todo sigue funcionando hoy, y anunciaremos una fecha de retirada antes de que nada deje de hacerlo. Para lo que sirve este aviso es para la decisión que tienes delante: **no construyas nada nuevo encima**, y si ya lo has hecho, cuenta con moverte. El resto de esta sección, los modelos, no se ve afectado.
+
+
Además de los modelos, NaN expone sus propias herramientas a través de un servidor **MCP** ([Model Context Protocol](https://modelcontextprotocol.io)). Sirve para lo contrario que el resto de esta sección: aquí no le das modelos a tu agente, le das **capacidades**.
-Hoy la herramienta disponible es la **búsqueda web**. El registro irá creciendo, así que pregúntale al servidor qué tiene en vez de fiarte de esta frase.
+La única herramienta es la **búsqueda web**, y está deprecada. Lo que viene debajo describe lo que sigue funcionando hoy.
| Campo | Valor |
|---|---|
diff --git a/src/content/docs-es/models.mdx b/src/content/docs-es/models.mdx
index a1c0431..e899715 100644
--- a/src/content/docs-es/models.mdx
+++ b/src/content/docs-es/models.mdx
@@ -299,6 +299,7 @@ OpenAI y la misma `base URL`.
{ label: 'Modalidades', value: 'texto→imagen · imagen→imagen' },
{ label: 'Resolución', value: '256 a 1536 px (múltiplos de 16)' },
{ label: 'Imágenes / petición', value: '1 a 4 (n)' },
+ { label: 'Ritmo', value: '1 pet/s · ráfaga 3' },
{ label: 'Cuota mensual', value: '100 peticiones / miembro' },
]}
items={[
diff --git a/src/content/docs-es/nan-cli.mdx b/src/content/docs-es/nan-cli.mdx
index dd0de9a..6ee2a6f 100644
--- a/src/content/docs-es/nan-cli.mdx
+++ b/src/content/docs-es/nan-cli.mdx
@@ -81,13 +81,12 @@ En Windows, desde PowerShell:
irm https://nan.builders/install.ps1 | iex
```
-Hace el mismo trabajo: resuelve la última release, descarga el `.zip` de tu arquitectura, **verifica su checksum** y deja `nan.exe` en `%LOCALAPPDATA%\Programs
-an`, añadiendo esa carpeta a tu `PATH` de usuario si no estaba. Las terminales que ya tuvieras abiertas no lo verán hasta que las reinicies.
+Hace el mismo trabajo: resuelve la última release, descarga el `.zip` de tu arquitectura, **verifica su checksum** y deja `nan.exe` en `%LOCALAPPDATA%\Programs\nan`, añadiendo esa carpeta a tu `PATH` de usuario si no estaba. Las terminales que ya tuvieras abiertas no lo verán hasta que las reinicies.
Instala para tu usuario y no para toda la máquina, a propósito: el equivalente en Windows del `sudo` es un diálogo de elevación saliendo de un script por tubería, que es peor. Para ponerlo en otro sitio:
```powershell
-& ([scriptblock]::Create((irm https://nan.builders/install.ps1))) -InstallDir "C: ools"
+& ([scriptblock]::Create((irm https://nan.builders/install.ps1))) -InstallDir "C:\tools"
```
Hay binarios para macOS, Linux y Windows, en Intel y en ARM.
@@ -130,7 +129,7 @@ Dentro de OpenCode, `/models` te enseña los modelos de NaN ya disponibles.
-Es la vía para Windows, y la que quieres si vas a tocar el CLI. Hace falta [Go](https://go.dev) 1.26 o superior:
+Es la que quieres si vas a tocar el CLI. Hace falta [Go](https://go.dev) 1.26 o superior:
```bash
git clone https://github.com/helmcode/nan-cli
@@ -183,7 +182,6 @@ El resultado es el mismo. Lo único que te pierdes son las pestañas de consumo
-- **En Windows hay que compilar.** Las versiones publicadas traen binarios de macOS y Linux; para Windows, de momento, la vía es `go build`.
-- **El instalador pide la lista de versiones a GitHub.** Si estás detrás de un proxy que bloquea `api.github.com`, no encontrará nada que descargar. En ese caso, baja el `.tar.gz` de tu sistema a mano desde la [página de releases](https://github.com/helmcode/nan-cli/releases).
+- **El instalador pide la lista de versiones a GitHub.** Si estás detrás de un proxy que bloquea `api.github.com`, no encontrará nada que descargar. En ese caso, baja a mano el archivo de tu sistema desde la [página de releases](https://github.com/helmcode/nan-cli/releases).
diff --git a/src/content/docs/agent-setup.mdx b/src/content/docs/agent-setup.mdx
index c2d6c15..5b0e18c 100644
--- a/src/content/docs/agent-setup.mdx
+++ b/src/content/docs/agent-setup.mdx
@@ -119,7 +119,7 @@ Yours is not here? If it accepts an OpenAI base URL and an API key, it works. Co
name: 'MCP server',
href: '/docs/mcp',
kind: 'Tools',
- note: 'NaN\'s web search inside any MCP-compatible agent.',
+ note: 'Deprecated. NaN\'s web search inside any MCP-compatible agent, being retired along with it.',
},
]}
/>
diff --git a/src/content/docs/agents.md b/src/content/docs/agents.md
index cc3f17d..e6a0daa 100644
--- a/src/content/docs/agents.md
+++ b/src/content/docs/agents.md
@@ -10,7 +10,7 @@ group: Guides
NaN Cloud lets you deploy AI agents in your own **microVM**: a lightweight virtual machine with QEMU + KVM, its own kernel, its own filesystem, and full root access. Isolated from the host and from other members. The first available agent type is **Hermes**.
> **Using an agent you host yourself?**
-> If you run your own MCP-compatible agent elsewhere, you can plug our tools (such as web search) straight into it with the same API key via our remote [MCP server](/docs/api#tag/mcp).
+> If you run your own MCP-compatible agent elsewhere, you can plug our tools (such as web search) straight into it with the same API key via our remote [MCP server](/docs/api#tag/mcp). Note that the MCP server and web search are both **deprecated** and are being retired.
## Architecture
diff --git a/src/content/docs/claude-code.mdx b/src/content/docs/claude-code.mdx
index da5f3ee..6e82134 100644
--- a/src/content/docs/claude-code.mdx
+++ b/src/content/docs/claude-code.mdx
@@ -201,4 +201,4 @@ On either path, avoid `glm5.3` for tasks that involve reading screenshots: it do
## NaN's tools, separately
-Whichever path you choose, you can give Claude Code the cluster's web search with a single command. It is in [MCP server](/docs/mcp).
+Whichever path you choose, you can give Claude Code the cluster's web search with a single command. It is in [MCP server](/docs/mcp) - which is **deprecated**: it still works today, but it is being retired along with web search, so do not build on it.
diff --git a/src/content/docs/examples.md b/src/content/docs/examples.md
index 776ec1c..13091ef 100644
--- a/src/content/docs/examples.md
+++ b/src/content/docs/examples.md
@@ -187,7 +187,7 @@ for r in response["results"]:
print(f"{r['index']}: {r['relevance_score']:.3f}")
```
-Also works with raw `requests` or any HTTP client — the endpoint is OpenAI-compatible in authentication and payload format.
+Also works with raw `requests` or any HTTP client — send the JSON body with your Bearer key. `/rerank` is an endpoint of ours, not part of the OpenAI specification: the authentication is the same one, the body is ours.
## model: kokoro
@@ -472,10 +472,12 @@ console.log(image.data[0].url);
`/images/edits` takes up to four reference images (PNG, JPEG or WebP, under 25 MB each) and does not support `mask`: sending one returns `400`.
-Images need inference membership, `403` otherwise, and they run on their own budget: 20 requests per minute and 100 per month, which does not touch your token quota.
+Images need inference membership, `403` otherwise, and they run on their own budget, which does not touch your token quota and is not your key's either: image generation does not go through the shared inference API at all. One request per second with a burst of 3, and 100 requests per calendar month. A request asking for several images still costs one.
## tool: web search
+**Deprecated.** Web search is being retired, through this endpoint and through the [MCP server](/docs/mcp) alike. It still works today and a removal date will be announced before it stops, but do not build anything new on it.
+
authenticated web search for agents — `POST /v1/search`
### curl
diff --git a/src/content/docs/gentle-ai.mdx b/src/content/docs/gentle-ai.mdx
index 052576a..1fdc5d1 100644
--- a/src/content/docs/gentle-ai.mdx
+++ b/src/content/docs/gentle-ai.mdx
@@ -131,5 +131,5 @@ It is worth running `sync` after every `upgrade`: the first updates the program,
## Next steps
- [Set up your agent](/docs/agent-setup): connect your tool to the cluster first.
-- [MCP server](/docs/mcp): add NaN's web search to your agent as well.
+- [MCP server](/docs/mcp): add NaN's web search to your agent as well. **Deprecated**, being retired along with web search.
- [Choose your model](/docs/choose-a-model): which model to ask for each task.
diff --git a/src/content/docs/getting-started.mdx b/src/content/docs/getting-started.mdx
index 089d691..abbde2c 100644
--- a/src/content/docs/getting-started.mdx
+++ b/src/content/docs/getting-started.mdx
@@ -153,7 +153,7 @@ The full detail, endpoint by endpoint, is in the [API reference](/docs/api).
Two limits are per API key and apply to everything you call: requests per minute, and requests at once.
-On top of those, some models carry one of their own: a tokens-per-minute ceiling on the big chat models, and a requests-per-minute one on `rerank`. `glm5.3` is not gated per minute at all, but by a rolling token window plus an allowance per billing period. Web search runs on a budget separate from the models'.
+On top of those, every chat model carries a tokens-per-minute ceiling of its own, and they are not the same number: each one is that model's context window times how many times a minute you may refill it. The non-chat endpoints, `rerank`, `qwen3-embedding`, `kokoro` and `whisper`, carry none of their own, which does not make them free: your key's 60 a minute still count them. `glm5.3` has a ceiling like the rest, but what gates it in practice is a rolling token window plus an allowance per billing period. Web search runs on a budget separate from the models'.
The current figures are at the end of [Models](/docs/models), which is where they are published so that no two versions of the same number go around.
diff --git a/src/content/docs/intro.md b/src/content/docs/intro.md
index 8166ab8..f66df0a 100644
--- a/src/content/docs/intro.md
+++ b/src/content/docs/intro.md
@@ -28,7 +28,7 @@ Limits are per API key — a cap on requests per minute and a maximum number of
- [Choose your model](/docs/choose-a-model): which model to ask for each task, and how its id is spelled.
- [Set up your agent](/docs/agent-setup): Claude Code, Codex, Cursor, Cline, OpenCode, Zed and company.
- [NaN CLI](/docs/nan-cli): the official terminal tool, which also configures several of them for you.
-- [MCP server](/docs/mcp): NaN's web search inside your agent.
+- [MCP server](/docs/mcp): NaN's web search inside your agent. **Deprecated**, being retired along with web search.
- [API reference](/docs/api): every endpoint, field by field.
- [Models](/docs/models): the spec sheets and the limits.
- [Examples](/docs/examples): snippets in Python, Node.js and curl.
diff --git a/src/content/docs/mcp.mdx b/src/content/docs/mcp.mdx
index 924be65..f1b01ae 100644
--- a/src/content/docs/mcp.mdx
+++ b/src/content/docs/mcp.mdx
@@ -1,17 +1,24 @@
---
title: MCP server
-description: Plug NaN's web search into any MCP-compatible agent.
+description: "Deprecated: NaN's web search inside any MCP-compatible agent. Being retired along with web search itself."
order: 16
group: Set up your agent
---
import Details from '../../components/docs/Details.astro';
+import Callout from '../../components/docs/Callout.astro';
# MCP server.
+
+Web search is going away, through the API and through this server alike, and web search is the only tool this server has. So the MCP server goes with it.
+
+It all still works today, and a removal date will be announced before anything stops. What this notice is for is the decision in front of you: **do not build anything new on it**, and if you already have, plan on moving off. Everything else in this section, the models, is unaffected.
+
+
On top of the models, NaN exposes its own tools through an **MCP** server ([Model Context Protocol](https://modelcontextprotocol.io)). It is for the opposite of the rest of this section: here you are not giving your agent models, you are giving it **capabilities**.
-Today the available tool is **web search**. The registry will grow, so ask the server what it has rather than trusting this sentence.
+The only tool is **web search**, and it is deprecated. The page below describes what is still running today.
| Field | Value |
|---|---|
diff --git a/src/content/docs/models.mdx b/src/content/docs/models.mdx
index b4a3e0b..6283705 100644
--- a/src/content/docs/models.mdx
+++ b/src/content/docs/models.mdx
@@ -298,6 +298,7 @@ with the same `base URL`.
{ label: 'Modalities', value: 'text→image · image→image' },
{ label: 'Resolution', value: '256–1536 px (multiples of 16)' },
{ label: 'Images / request', value: '1–4 (n)' },
+ { label: 'Rate', value: '1 req/s · burst 3' },
{ label: 'Monthly quota', value: '100 requests / member' },
]}
items={[
diff --git a/src/content/docs/nan-cli.mdx b/src/content/docs/nan-cli.mdx
index 0d62b44..61c0f16 100644
--- a/src/content/docs/nan-cli.mdx
+++ b/src/content/docs/nan-cli.mdx
@@ -81,13 +81,12 @@ On Windows, from PowerShell:
irm https://nan.builders/install.ps1 | iex
```
-It does the same work: resolves the latest release, downloads the `.zip` for your architecture, **verifies its checksum** and puts `nan.exe` in `%LOCALAPPDATA%\Programs
-an`, adding that directory to your user `PATH` if it is not there already. Terminals you already had open will not see it until you restart them.
+It does the same work: resolves the latest release, downloads the `.zip` for your architecture, **verifies its checksum** and puts `nan.exe` in `%LOCALAPPDATA%\Programs\nan`, adding that directory to your user `PATH` if it is not there already. Terminals you already had open will not see it until you restart them.
It installs for your user and not for the whole machine, deliberately: the Windows equivalent of the `sudo` prompt is an elevation dialog out of a piped script, which is worse. To put it elsewhere:
```powershell
-& ([scriptblock]::Create((irm https://nan.builders/install.ps1))) -InstallDir "C: ools"
+& ([scriptblock]::Create((irm https://nan.builders/install.ps1))) -InstallDir "C:\tools"
```
There are binaries for macOS, Linux and Windows, on Intel and on ARM.
@@ -130,7 +129,7 @@ Inside OpenCode, `/models` shows you the NaN models, already available.
-This is the path on Windows, and the one you want if you are going to work on the CLI itself. You need [Go](https://go.dev) 1.26 or newer:
+This is the one you want if you are going to work on the CLI itself. You need [Go](https://go.dev) 1.26 or newer:
```bash
git clone https://github.com/helmcode/nan-cli
@@ -183,7 +182,6 @@ The result is the same. The only thing you miss out on are the usage and cost ta
-- **On Windows you have to build.** The published releases carry macOS and Linux binaries; for Windows, the path for now is `go build`.
-- **The installer asks GitHub for the list of releases.** If you are behind a proxy that blocks `api.github.com`, it will find nothing to download. In that case, grab the `.tar.gz` for your system by hand from the [releases page](https://github.com/helmcode/nan-cli/releases).
+- **The installer asks GitHub for the list of releases.** If you are behind a proxy that blocks `api.github.com`, it will find nothing to download. In that case, grab the archive for your system by hand from the [releases page](https://github.com/helmcode/nan-cli/releases).
diff --git a/src/data/openapi.json b/src/data/openapi.json
index 989ae4a..455a24b 100644
--- a/src/data/openapi.json
+++ b/src/data/openapi.json
@@ -56,11 +56,11 @@
},
{
"name": "Search",
- "description": "Authenticated web search for agents."
+ "description": "**Deprecated.** Web search is being retired, through this API and through the MCP server alike. It still works today, and a removal date will be announced before it stops. Do not build anything new on it.\n\nAuthenticated web search for agents."
},
{
"name": "MCP",
- "description": "Remote MCP server for agents and MCP clients."
+ "description": "**Deprecated.** Web search is being retired, through this API and through the MCP server alike. It still works today, and a removal date will be announced before it stops. Do not build anything new on it.\n\nRemote MCP server for agents and MCP clients."
}
],
"paths": {
@@ -1404,7 +1404,8 @@
"Search"
],
"summary": "Web search",
- "description": "An authenticated web search tool for agents. Give it a query and it returns ranked results (title, URL, snippet, source), drawn from a hybrid of upstream search providers. Results come back through the NaN API, so your key never talks to a third-party search provider directly, and you never hold a provider key.\n\nSet `fetch_content: true` to also extract the readable main text of the top results (adds latency). You supply only `query`; when `fetch_content` is `true` the server fetches page content **only** for the URLs the search returned, through a hardened anti-SSRF fetcher, so you cannot pass an arbitrary URL to fetch.\n\nLimits are per API key and separate from the model endpoints, so searching does not consume your chat RPM budget or vice versa: 20 requests per minute, 3 concurrent, and 500 searches per day. Exceeding the per-minute or concurrency limit returns `429` `rate_limit_exceeded`; exhausting the daily quota returns `429` `insufficient_quota`. A `429` carries a `Retry-After` header. Repeated identical queries within ~15 minutes are served from a short-lived cache (`cached: true`); cached hits still count toward your rate and quota.\n\n## Use it as an agent tool\n\nDrop this OpenAI-style function schema into your model call's `tools` array. When the model emits a `web_search` tool call, invoke `POST /v1/search` with the arguments and feed the JSON response back as the tool result.\n\n```json\n{\n \"type\": \"function\",\n \"function\": {\n \"name\": \"web_search\",\n \"description\": \"Search the public web and return relevant results (title, URL, snippet, and optional page content). Use it when the answer may depend on current events, recent developments, prices, release/version numbers, or facts you are not confident are up to date.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"query\": { \"type\": \"string\", \"description\": \"The web search query.\" },\n \"count\": { \"type\": \"integer\", \"description\": \"Number of results to return (1-20).\", \"minimum\": 1, \"maximum\": 20, \"default\": 5 },\n \"freshness\": { \"type\": \"string\", \"description\": \"Restrict results by recency: 'pd' (past day), 'pw' (past week), 'pm' (past month), 'py' (past year), or a 'YYYY-MM-DDtoYYYY-MM-DD' date range. Omit for no time filter.\" },\n \"fetch_content\": { \"type\": \"boolean\", \"description\": \"When true, also fetch and include the readable text of the top results (slower). Default false returns snippets only.\", \"default\": false }\n },\n \"required\": [\"query\"]\n }\n }\n}\n```",
+ "deprecated": true,
+ "description": "**Deprecated.** Web search is being retired, through this API and through the MCP server alike. It still works today, and a removal date will be announced before it stops. Do not build anything new on it.\n\nAn authenticated web search tool for agents. Give it a query and it returns ranked results (title, URL, snippet, source), drawn from a hybrid of upstream search providers. Results come back through the NaN API, so your key never talks to a third-party search provider directly, and you never hold a provider key.\n\nSet `fetch_content: true` to also extract the readable main text of the top results (adds latency). You supply only `query`; when `fetch_content` is `true` the server fetches page content **only** for the URLs the search returned, through a hardened anti-SSRF fetcher, so you cannot pass an arbitrary URL to fetch.\n\nLimits are per API key and separate from the model endpoints, so searching does not consume your chat RPM budget or vice versa: 20 requests per minute, 3 concurrent, and 500 searches per day. Exceeding the per-minute or concurrency limit returns `429` `rate_limit_exceeded`; exhausting the daily quota returns `429` `insufficient_quota`. A `429` carries a `Retry-After` header. Repeated identical queries within ~15 minutes are served from a short-lived cache (`cached: true`); cached hits still count toward your rate and quota.\n\n## Use it as an agent tool\n\nDrop this OpenAI-style function schema into your model call's `tools` array. When the model emits a `web_search` tool call, invoke `POST /v1/search` with the arguments and feed the JSON response back as the tool result.\n\n```json\n{\n \"type\": \"function\",\n \"function\": {\n \"name\": \"web_search\",\n \"description\": \"Search the public web and return relevant results (title, URL, snippet, and optional page content). Use it when the answer may depend on current events, recent developments, prices, release/version numbers, or facts you are not confident are up to date.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"query\": { \"type\": \"string\", \"description\": \"The web search query.\" },\n \"count\": { \"type\": \"integer\", \"description\": \"Number of results to return (1-20).\", \"minimum\": 1, \"maximum\": 20, \"default\": 5 },\n \"freshness\": { \"type\": \"string\", \"description\": \"Restrict results by recency: 'pd' (past day), 'pw' (past week), 'pm' (past month), 'py' (past year), or a 'YYYY-MM-DDtoYYYY-MM-DD' date range. Omit for no time filter.\" },\n \"fetch_content\": { \"type\": \"boolean\", \"description\": \"When true, also fetch and include the readable text of the top results (slower). Default false returns snippets only.\", \"default\": false }\n },\n \"required\": [\"query\"]\n }\n }\n}\n```",
"requestBody": {
"required": true,
"content": {
@@ -1518,7 +1519,8 @@
"MCP"
],
"summary": "MCP server (JSON-RPC)",
- "description": "Remote [Model Context Protocol](https://modelcontextprotocol.io) server, so our tools can be used inside any MCP-compatible agent or client with the same `sk-` key as the REST API.\n\nTransport is streamable HTTP and stateless; the protocol is JSON-RPC 2.0 with the methods `initialize`, `tools/list`, `tools/call` and `ping`. Today the server exposes a single tool, `web_search`, with the same arguments as [Web search](#tag/Search); it is a growing registry, so use `tools/list` to discover the current set.\n\nMCP calls share the **same** per-key rate limit, daily quota and concurrency as the equivalent REST endpoint, so there is no separate budget. A `web_search` tool call over MCP counts exactly like a `POST /v1/search` request.\n\nNote this endpoint lives at the host root, `https://api.nan.builders/mcp`, not under `/v1`.",
+ "deprecated": true,
+ "description": "**Deprecated.** Web search is being retired, through this API and through the MCP server alike. It still works today, and a removal date will be announced before it stops. Do not build anything new on it.\n\nRemote [Model Context Protocol](https://modelcontextprotocol.io) server, so our tools can be used inside any MCP-compatible agent or client with the same `sk-` key as the REST API.\n\nTransport is streamable HTTP and stateless; the protocol is JSON-RPC 2.0 with the methods `initialize`, `tools/list`, `tools/call` and `ping`. Today the server exposes a single tool, `web_search`, with the same arguments as [Web search](#tag/Search); it is a growing registry, so use `tools/list` to discover the current set.\n\nMCP calls share the **same** per-key rate limit, daily quota and concurrency as the equivalent REST endpoint, so there is no separate budget. A `web_search` tool call over MCP counts exactly like a `POST /v1/search` request.\n\nNote this endpoint lives at the host root, `https://api.nan.builders/mcp`, not under `/v1`.",
"requestBody": {
"required": true,
"content": {
diff --git a/src/env.d.ts b/src/env.d.ts
index 4addc10..ba0ad6b 100644
--- a/src/env.d.ts
+++ b/src/env.d.ts
@@ -13,6 +13,10 @@ declare namespace Cloudflare {
// Optional: both fall back to the defaults in src/lib/rateLimits.ts.
RATE_LIMIT_RPM?: string;
RATE_LIMIT_PARALLEL?: string;
+ // Optional and unset today. With no URL the docs render from the built-in
+ // table and never call out; see src/lib/limitsPolicy.ts.
+ LIMITS_POLICY_URL?: string;
+ LIMITS_POLICY_TOKEN?: string;
}
}
diff --git a/src/layouts/Docs.astro b/src/layouts/Docs.astro
index 73576df..528678b 100644
--- a/src/layouts/Docs.astro
+++ b/src/layouts/Docs.astro
@@ -46,6 +46,14 @@ const T = {
next: 'Next →',
docs: 'Docs',
close: 'Close menu',
+ searchAria: 'Search documentation',
+ sidebarAria: 'Documentation',
+ noResults: 'No results',
+ copy: 'Copy',
+ copied: 'Copied',
+ copyAria: 'Copy',
+ copyToast: 'Copied to clipboard',
+ copyFailed: 'Copy failed',
},
es: {
onThisPage: 'En esta página',
@@ -55,6 +63,14 @@ const T = {
next: 'Siguiente →',
docs: 'Docs',
close: 'Cerrar menú',
+ searchAria: 'Buscar en la documentación',
+ sidebarAria: 'Documentación',
+ noResults: 'Sin resultados',
+ copy: 'Copiar',
+ copied: 'Copiado',
+ copyAria: 'Copiar',
+ copyToast: 'Copiado al portapapeles',
+ copyFailed: 'No se pudo copiar',
},
}[lang];
@@ -206,7 +222,7 @@ const searchData = [