Blog Post

Azure Database for PostgreSQL Blog
6 MIN READ

Fueling the Agentic Web Revolution with NLWeb and PostgreSQL

abeomor-msft's avatar
abeomor-msft
Icon for Microsoft rankMicrosoft
Jul 30, 2025

PostgreSQL and NLWeb can easily transform any website into an AI-powered application or Model Context Protocol (MCP) server!

We’re excited to announce that NLWeb (Natural Language Web), Microsoft’s open project for natural language interfaces on websites now supports PostgreSQL. With this enhancement, developers can leverage PostgreSQL and NLWeb to transform any website into an AI-powered application or Model Context Protocol (MCP) server. This integration allows organizations to utilize a familiar, robust database as the foundation for conversational AI experiences, streamlining deployment and maximizing data security and scalability.

 

Soon, autonomous agents, not just human users, will consume and interpret website content, transforming how information is accessed and utilized online. During Microsoft //Build 2025, Microsoft introduced the era of the open agentic web, in which the internet is an open agentic web a new paradigm in which autonomous agents seamlessly interact across individual, organizational, team and end-to-end business contexts. To realize the future of an open agentic web, Microsoft announced the NLWeb project. NLWeb transforms any website to an AI-powered application with just a few lines of code and by connecting to an AI model and a knowledge base.

 

In this post, we’ll cover:

  • What NLWeb is and how it works with vector databases
  • How pgvector enables vector similarity search in PostgreSQL for NLWeb
  • Get started using NLWeb with Postgres

Let’s dive in and see how Postgres + NLWeb can redefine conversational web interfaces while keeping your data in a familiar, powerful database.

 

What is NLWeb? A Quick Overview of Conversational Web Interfaces

NLWeb is an open project developed by Microsoft to simplify adding conversational AI interfaces to websites.

How NLWeb works under the hood:

  1. Processes existing data/website content that exists in semi-structured formats like Schema.org, RSS, and other data that websites already publish
  2. Embeds and indexes all the content in a vector store (i.e PostgreSQL with pgvector)
  3. Routes user queries through several processes which handle natural langague understanding, reranking and retrieval.
  4. Answers queries with an LLM

The result is a high-quality natural language interface on top of web data, giving developers the ability to let users “talk to” web data. 

 

By default, every NLWeb instance is also a Model Context Protocol (MCP) server, allowing websites to make their content discoverable and accessible to agents and other participants in the MCP ecosystem if they choose.

 

Importantly, NLWeb is platform-agnostic and supports many major operating systems, AI models, and vector stores and the NLWeb project is modular by design, so developers can bring their own retrieval system, model APIs, and define their own extensions.

NLWeb with PostgreSQL

PostgreSQL is now embedded into the NLWeb reference stack as a native retriever, creating a scalable and flexible path for deploying NLWeb instances using open-source infrastructure.

Retrieval Powered by pgvector

NLWeb leverages pgvector, a PostgreSQL extension for efficient vector similarity search, to handle natural language retrieval at scale. By integrating pgvector into the NLWeb stack, teams can eliminate the need for external vector databases. Web data stored in PostgreSQL becomes immediately searchable and usable for NLWeb experiences, streamlining infrastructure and enhancing security.

PostgreSQL's robust governance features and wide adoption align with NLWeb’s mission to enable conversational AI for any website or content platform. With pgvector retrieval built in, developers can confidently launch NLWeb instances on their own databases no additional infrastructure required.

Implementation example

We are going to use NLWeb and Postgres, to create a conversational AI app and MCP server that will let us chat with content from the Talking Postgres with Claire Giordano Podcast!

Prerequisites

  1. An active Azure account.
  1. Enable and configure the pg_vector extensions.
  2. Create an Azure AI Foundry project.
  3. Deploy models gpt-4.1, gpt-4.1-mini and text-embedding-3-small.
  4. Install Visual Studio Code.
  5. Install the Python extension.
  6. Install Python 3.11.x.
  7. Install the Azure CLI (latest version).

Getting started

All the code and sample datasets are available in this GitHub repository.

Step 1: Setup NLWeb Server

1. Clone or download the code from the repo.

git clone https://github.com/microsoft/NLWeb
cd NLWeb

2. Open a terminal to create a virtual python environment and activate it.

python -m venv myenv
source myenv/bin/activate    # Or on Windows: myenv\Scripts\activate

3. Go to the 'code/python' folder in NLWeb to install the dependencies.

cd code/python
pip install -r requirements.txt

4. Go to the project root folder in NLWeb and copy the .env.template file to a new .env file

cd ../../
cp .env.template .env

5. In the .env file, update the API key you will use for your LLM endpoint of choice and update the Postgres connection string. For example:

AZURE_OPENAI_ENDPOINT="https://TODO.openai.azure.com/"
AZURE_OPENAI_API_KEY="<TODO>"

# If using Postgres connection string
POSTGRES_CONNECTION_STRING="postgresql://<HOST>:<PORT>/<DATABASE>?user=<USERNAME>&sslmode=require"
POSTGRES_PASSWORD="<PASSWORD>"

6. Update your config files (located in the config folder) to make sure your preferred providers match your .env file. There are three files that may need changes.

    • config_llm.yaml: Update the first line to the LLM provider you set in the .env file.
      • By default it is Azure OpenAI. You can also adjust the models you call here by updating the models noted. By default, we are assuming 4.1 and 4.1-mini.
    • config_embedding.yaml: Update the first line to your preferred embedding provider.
      • By default it is Azure OpenAI, using text-embedding-3-small.
    • config_retrieval.yaml: Update the first line to postgres.
      • You should update write_endpoint to postgres and
      • You should update postgres retrieval endpoint is enabled to 'true' in the following list of possible endpoints.

Step 2: Initialize Postgres Server

  1. Go to the 'code/python/misc folder in NLWeb to run Postgres initializer.

NOTE: If you are using Azure Postgres Flexible server make sure you have `vector` extension allow-listed and make sure the database has the vector extension enabled,

cd code/python/misc
python postgres_load.py

 

Step 3: Ingest Data from Talk Postgres Podcast

  1. Now we will load some data in our local vector database to test with. We've listed a few RSS feeds you can choose from below. Go to the 'code/python folder in NLWeb and run the command.

The format of the command is as follows (make sure you are still in the 'python' folder when you run this):

python -m data_loading.db_load <RSS URL> <site-name>

Talking Postgres with Claire Giordano Podcast:

python -m data_loading.db_load https://feeds.transistor.fm/talkingpostgres Talking-Postgres 
  1. (Optional) You can check the documents table in your Postgres database and verify the table looks like the one below. To verify all the data from the website was uploaded.

Test NLWeb Server 

  1. Start your NLWeb server (again from the 'python' folder):
python app-file.py
  1. Go to http://localhost:8000/
  2. Start ask questions about the Talking Postgres with Claire Giordano Podcast, you may try different modes.

Trying List Mode:

Sample Prompt: “I want to listen to something that talks about the advances in vector search such as DiskANN”

 

 

 

 

Trying Generate Mode

Sample Prompt: “What did Shireesh Thota say about the future of Postgres?”

 

 

 

 

Running NLWeb with MCP

1. If you do not already have it, install MCP in your venv:

pip install mcp

 

2. Next, configure your Claude MCP server. If you don’t have the config file already, you can create the file at the following locations:

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json

The default MCP JSON file needs to be modified as shown below:

macOS Example Configuration

{
  “mcpServers”: {
    “ask_nlw”: {
      “command”: “/Users/yourname/NLWeb/myenv/bin/python”,
      “args”: [
        “/Users/yourname/NLWeb/code/chatbot_interface.py”,
        “—server”,
        “http://localhost:8000”,
        “—endpoint”,
        “/mcp”
      ],
      “cwd”: “/Users/yourname/NLWeb/code”
    }
  }
}

Windows Example Configuration

{
  “mcpServers”: {
    “ask_nlw”: {
      “command”: “C:\\Users\\yourusername\\NLWeb\\myenv\\Scripts\\python”,
      “args”: [
        “C:\\Users\\yourusername\\NLWeb\\code\\chatbot_interface.py”,
        “—server”,
        “http://localhost:8000”,
        “—endpoint”,
        “/mcp”
      ],
      “cwd”: “C:\\Users\\yourusername\\NLWeb\\code”
    }
  }
}

 

Note: For Windows paths, you need to use double backslashes (\\) to escape the backslash character in JSON.

3. Go to the 'code/python’ folder in NLWeb and run the command. Enter your virtual environment and start your NLWeb local server. Make sure it is configured to access the data you would like to ask about from Claude.

# On macOS
source ../myenv/bin/activate
python app-file.py

# On Windows
..\myenv\Scripts\activate
python app-file.py

 

4. Open Claude Desktop. It should ask you to trust the 'ask_nlw' external connection if it is configured correctly. After clicking yes and the welcome page appears, you should see 'ask_nlw' in the bottom right '+' options. Select it to start a query.

 

 

5. To query NLWeb, just type 'ask_nlw' in your prompt to Claude. You'll notice that you also get the full JSON script for your results. Remember, you must have your local NLWeb server started to use this option.

Learn More

Vector Store in Azure Postgres Flexible Server

Generative AI in Azure Postgres Flexible Server

NLWeb GitHub repo includes:

 

Updated Jul 30, 2025
Version 1.0

1 Comment

  • This is great! What about sites whose content is not structed into RSS feeds? Lets say something built with a documentation framework like docusaurus?