# NLWeb explained: what it is, how it relates to MCP, and what a site exposes

> NLWeb adds an ask endpoint to a site, answers in Schema.org JSON, and doubles as an MCP server. What it is, how it differs from MCP, and what a scan sees.

- Source: /learn/nlweb-explained
- Updated: 2026-11-01
- Reading time: 7 minutes
- Tags: NLWeb, MCP, Schema.org, Microsoft

---
NLWeb (Natural Language Web) is an open project that [Microsoft introduced on 19 May 2025](https://news.microsoft.com/source/features/company-news/introducing-nlweb-bringing-conversational-interfaces-directly-to-the-web/). It defines one core operation, `ask`, and ships a Python server that answers natural-language questions about a site’s data in JSON that uses Schema.org types. Every instance of that server is also an MCP server. This scanner has no check for NLWeb.

## What is NLWeb?

The [README](https://github.com/nlweb-ai/NLWeb) describes 2 parts: a protocol for asking a site a question, and an implementation that uses structured markup the site already has. Its examples are lists of products, recipes, attractions and reviews. The announcement credits R.V. Guha, who created RSS, RDF and Schema.org, with conceiving and developing it.

The code is MIT-licensed. The original address, `github.com/microsoft/NLWeb`, now redirects to `github.com/nlweb-ai/NLWeb`, and the README still lists a Microsoft support address. The README calls its code proof-of-concept demonstrations, not a definitive solution. On 31 October 2026 the repository had no releases, and the last commit on `main` was a dependency merge dated 10 June 2026.

## How does NLWeb answer a question?

The site owner loads Schema.org markup, JSONL or RSS into a vector database. The README lists Qdrant, Milvus, Snowflake, Azure AI Search, Elasticsearch, Postgres and Cloudflare AutoRAG. A query then runs a vector search. According to the [REST API doc](https://github.com/nlweb-ai/NLWeb/blob/b423f15/docs/nlweb-rest-api.md), every result carries a `score`, and a model from the provider you configure writes its description.

The [hello-world guide](https://github.com/nlweb-ai/NLWeb/blob/main/docs/nlweb-hello-world.md) shows the shortest path. After its configuration steps, run this from `AskAgent/python`:

```sh
python -m data_loading.db_load https://feeds.megaphone.fm/VMP5705694065 Today-Explained
python app-aiohttp.py
```

The first line loads a podcast RSS feed into a local Qdrant store under the site name `Today-Explained`. The second starts the server on port 8000.

The README says most production deployments connect NLWeb to live databases instead of copying content, to avoid stale answers. Each query spends model calls on your provider account.

The `mode` argument sets how much the model does. `list` returns the top matches, and `summarize` adds a summary. The reference server’s `generate` answers more like retrieval-augmented generation, and the specification defines only the first 2.

## What does an NLWeb site expose?

Version 0.55 of the [specification](https://github.com/nlweb-ai/website/blob/main/NLWEBSPEC.md) lists 2 HTTP endpoints in §7.1. The reference server’s code registers others, and it has no `/await` route.

| Path | What it does | Defined in |
|---|---|---|
| `/ask` | Answers a natural-language query | The specification and the reference server |
| `/await` | Checks on or cancels a promised result | The specification only |
| `/who` | Finds the agents or sites that can answer | The reference server only |
| `/sites` | Lists the sites in the backing store | The reference server only |
| `/mcp` | Offers the same questions as MCP tools | The reference server only |

The specification’s `/ask` takes a POST. The reference server takes GET and POST. This request follows the specification’s HTTP binding, with `example.com` as a placeholder:

```sh
SITE=https://example.com
curl -sS -X POST "$SITE/ask" \
  -H 'Content-Type: application/json' \
  -d '{"query":{"text":"healthy breakfast recipes with eggs"},"prefer":{"streaming":false},"meta":{"version":"0.55"}}'
```

It has not been run against a live site, because this article names no deployment it could verify. The reference server flattens this nested form, which a code comment calls the v0.55 structured request format. It also takes the flat arguments of its REST doc: `query`, `site`, `prev`, `mode` and `streaming`. In the reference server streaming is on by default, so a request without `streaming=false` returns an event stream.

The specification’s own example response is an `_meta` object plus an array of Schema.org items:

```json
{
  "_meta": {"response_type": "answer", "response_format": "conversational_search", "version": "0.55"},
  "results": [
    {
      "@type": "Recipe",
      "@context": "https://schema.org",
      "name": "Veggie-Packed Scrambled Eggs",
      "url": "https://recipes.example.com/veggie-scrambled-eggs",
      "cookTime": "PT15M"
    }
  ]
}
```

The shape is not settled. The older REST doc describes a `query_id` and results with `url`, `name`, `site`, `score`, `description` and `schema_object`. The [TypeSpec repository](https://github.com/nlweb-ai/nlweb-typespec), which says it is at version 0.5, defines a `content` array instead. Check which shape a server returns before you write a client.

Version 0.55 defines no discovery file, no `/.well-known` path and no link relation. A caller has to learn the endpoint’s address elsewhere. It leaves authentication and rate limiting to the transport, and recommends `429` with `Retry-After` for rate limits (§2.4 and §2.5).

## How is NLWeb different from MCP?

MCP standardizes how an agent calls any tool on a server. NLWeb standardizes one operation: a natural-language question to a site, with Schema.org items back. The README’s analogy is that NLWeb relates to MCP and A2A as HTML relates to HTTP.

NLWeb sits on top of MCP, not beside it. Appendix A of the specification defines `ask` and `await` as MCP tools. The reference server’s `/mcp` route lists `ask`, `list_sites` and, when its who endpoint is on, `who`.

| | MCP | NLWeb |
|---|---|---|
| Standardizes | How an agent calls tools, reads resources and gets prompts | `ask`, and `await` for long jobs, over HTTP or inside MCP |
| Who writes the answer | The tool’s own code | A model, over data you indexed |
| Shape of the result | Whatever the tool returns | An `_meta` object and Schema.org items |
| How an agent finds it | A [server card](/learn/mcp-server-card) or `server/discover` | Nothing in version 0.55 |
| Cost of a call | Whatever the tool does | Retrieval and model calls |

The reference server pins an old MCP revision. Its MCP wrapper answers `initialize` with protocol version `2024-11-05` whatever the client offers, and NLWeb_Core carries the same string. That predates 2025-11-25 and 2026-07-28. The [migration checklist](/learn/mcp-2026-07-28-migration) covers what the newer revisions changed.

## Does the AgenticWebScore scanner check NLWeb?

No. No check requests `/ask`, `/who` or `/sites`, and the rubric does not name NLWeb.

A site’s `/mcp` is a separate matter. The [MCP server check](/checks/mcp-server) opens a site’s MCP endpoint only when the scan has already seen an agent surface. A server card, an AI catalog entry, a homepage `Link` with the relation `mcp` or an API description each count. In a local test, a bare `/mcp` route was Not scored.

Where the check runs, it offers 2025-11-25 and accepts the version the server answers, so `2024-11-05` does not fail it. By the code, a plain GET to the reference server’s `/mcp` returns a JSON-RPC error with HTTP 200. The check’s `/mcp` probe reads that as an MCP signal. No NLWeb site has been scanned.

A check for NLWeb would need 3 things that do not exist yet:

- **A discovery signal.** Version 0.55 defines none, so a scan could only guess `/ask`.
- **A request that costs the site nothing.** `/ask` spends the site’s model budget. The scan calls no tool, so it could not send a question.
- **A stable specification.** The README links `https://nlweb.ai/spec`, which did not open over HTTPS on 31 October 2026: the certificate named only GitHub hosts. The version this article follows is a file in a repository, and 2 other documents describe other shapes.

Until then a scan says nothing about NLWeb, and this article does not promise a check. The scan does read the markup NLWeb indexes: [JSON-LD](/checks/jsonld) and the [sitemap](/checks/sitemap-xml).

## Who runs NLWeb?

Microsoft’s announcement says it worked with a small cohort of early adopters. It lists 12 initial publishing and ecosystem collaborators: a mix of publishers, platforms and database vendors. It does not say which of them run a public endpoint. This article names none, because naming a deployment means finding its live `/ask`, and none was verified.

## Should a site run NLWeb?

Choose by what you want agents to do.

- **Read your content.** Serve [markdown](/learn/markdown-content-negotiation), keep your structured data accurate, and publish [llms.txt](/learn/llms-txt-guide). None of that puts a model on your bill.
- **Act on your site.** Run an MCP server with typed tools, as [Tools, not pages](/learn/agent-tools-not-pages) describes, and test it with [curl](/learn/test-mcp-server-curl).
- **Ask open questions over a large catalog.** Recipes, events and products fit NLWeb. Budget for a vector database, model calls, authentication and rate limits.

To see what a scan reads on your site today, [scan it](/scan).
