nlweb-mcp-server
Expose NLWeb as an MCP (Model Context Protocol) server — JSON-RPC 2.0 endpoint at /mcp, the `ask` / `list_sites` / `who` tools, MCP protocol version 2024-11-05, and integration with ChatGPT, Claude, Gemini, and other agent clients. Use when wiring NLWeb to an AI agent via MCP or building an MCP client that consumes an NLWeb site.
Best use case
nlweb-mcp-server is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Expose NLWeb as an MCP (Model Context Protocol) server — JSON-RPC 2.0 endpoint at /mcp, the `ask` / `list_sites` / `who` tools, MCP protocol version 2024-11-05, and integration with ChatGPT, Claude, Gemini, and other agent clients. Use when wiring NLWeb to an AI agent via MCP or building an MCP client that consumes an NLWeb site.
Teams using nlweb-mcp-server should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/nlweb-mcp-server/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How nlweb-mcp-server Compares
| Feature / Agent | nlweb-mcp-server | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Expose NLWeb as an MCP (Model Context Protocol) server — JSON-RPC 2.0 endpoint at /mcp, the `ask` / `list_sites` / `who` tools, MCP protocol version 2024-11-05, and integration with ChatGPT, Claude, Gemini, and other agent clients. Use when wiring NLWeb to an AI agent via MCP or building an MCP client that consumes an NLWeb site.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# NLWeb MCP Server
## Before writing code
**Fetch live spec**:
1. Fetch https://github.com/nlweb-ai/NLWeb/blob/main/docs/nlweb-rest-api.md (covers `/mcp` route alongside `/ask`).
2. Read `AskAgent/python/webserver/mcp_wrapper.py` in the live repo for the **exact JSON-RPC method list and tool schemas** — these change between releases.
3. Fetch https://github.com/nlweb-ai/NLWeb/blob/main/docs/nlweb-chatgpt-integration.md for the ChatGPT-specific wiring.
4. Cross-reference with the MCP specification at https://modelcontextprotocol.io for transport rules.
5. Web-search the latest release notes for any MCP-related changes — the wrapper file's own docstring warns "Backwards compatibility is not guaranteed."
## Conceptual Architecture
### How NLWeb Implements MCP
NLWeb is **already an MCP server** out of the box — same code, second binding. The `/mcp` route in `webserver/routes/mcp.py` accepts JSON-RPC 2.0 requests and re-uses the same `NLWebHandler` pipeline as `/ask`. No separate process, no extra config.
### Routes
| Route | Method | Purpose |
|-------|--------|---------|
| `/mcp` | POST, GET | Main JSON-RPC endpoint |
| `/mcp/{path}` | POST, GET | Path-scoped variant |
| `/mcp/health` | GET | Liveness check |
### MCP Protocol Version
NLWeb identifies itself with MCP protocol version `2024-11-05` and server name `nlweb-mcp-server`. **Pin to this protocol version** in clients until you verify a newer one is supported.
### JSON-RPC Methods Supported
| Method | Direction | Notes |
|--------|-----------|-------|
| `initialize` | client → server | Handshake; returns server capabilities |
| `initialized` | client → server | Notification; no response |
| `tools/list` | client → server | Returns the tool definitions |
| `tools/call` | client → server | Invoke a tool |
| `notifications/cancelled` | client → server | Cancel an in-flight tool call |
(`prompts/list` and `prompts/get` appear in some docs but are not in `mcp_wrapper.py` at the time of writing — verify.)
### Tools Exposed
Three tools are advertised via `tools/list`:
#### 1. `ask` — the primary NL query
```json
{
"name": "ask",
"description": "Ask a natural-language question grounded in the site's Schema.org content.",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" },
"site": { "type": "array", "items": { "type": "string" } },
"generate_mode": { "type": "string", "enum": ["list", "summarize", "generate"] }
},
"required": ["query"]
}
}
```
Note that the MCP `ask` tool takes `site` as an **array** (where the REST `/ask` takes a single string). Map accordingly in clients.
#### 2. `list_sites` — enumeration
```json
{ "name": "list_sites", "description": "List all sites the agent can query.", "inputSchema": { "type": "object", "properties": {} } }
```
#### 3. `who` — federated discovery (conditional)
Only present when `who_endpoint_enabled: true` in `config_nlweb.yaml`. Takes `{query}`, returns the best NLWeb site(s) for that query — used for federated search across sites.
### Streaming inside MCP
JSON-RPC 2.0 itself is request/response — no streaming. NLWeb's `/mcp` is **NOT SSE by default**. SSE only activates when the inner `ask` tool is called with `streaming: true` in its args. Most MCP clients don't expect that, so for cross-agent compatibility leave streaming off in MCP and turn it on only for clients you control.
### Error Format
JSON-RPC 2.0 errors:
```json
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32603,
"message": "Internal error",
"data": { "errors": [...] }
}
}
```
Common codes: `-32700` parse error, `-32600` invalid request, `-32601` method not found, `-32602` invalid params, `-32603` internal error.
### Two Parallel MCP Wrappers
NLWeb actually ships **two** MCP integrations:
| Wrapper | Path | Purpose |
|---------|------|---------|
| `webserver/mcp_wrapper.py` | `/mcp` on the aiohttp server (port 8000) | The canonical Python MCP server |
| `openai-apps-sdk-integration/nlweb_server_node/` | Separate Node.js/TypeScript process | Adds a React widget for ChatGPT Apps SDK — registers a `nlweb-list` tool and serves `ui://widget/nlweb-list.html` |
There's also an **A2A wrapper** (`webserver/a2a_wrapper.py`, route `a2a.py`) for Google's Agent-to-Agent protocol, and an **AppSDK adapter** on port 8100 (`appsdk_adapter_server.py`) that translates NLWeb's message list to OpenAI Apps SDK envelopes for existing clients.
## Implementation Guidance
### Server-Side: Just use the built-in /mcp
You don't typically write an MCP server for NLWeb — it's already there. What you might do:
1. **Verify `tools/list`** matches your needs by hitting it from your agent client.
2. **Customize the tool description** if your site needs a more specific prompt — patch `mcp_wrapper.py::handle_tools_list` carefully (you'll re-merge on upgrade).
3. **Add authentication** via middleware (`webserver/middleware/`) — MCP has no built-in auth; bring your own (bearer token, OAuth proxy, etc.).
4. **Disable `who`** for offline / single-site deployments by setting `who_endpoint_enabled: false`.
### Client-Side: Connecting an agent to NLWeb
```python
# Sketch — verify against latest MCP client SDK
import httpx, json
async def mcp_call(url, method, params=None):
payload = {"jsonrpc": "2.0", "id": 1, "method": method, "params": params or {}}
async with httpx.AsyncClient() as c:
r = await c.post(url, json=payload, timeout=60)
return r.json()
# Handshake
await mcp_call("http://localhost:8000/mcp", "initialize", {"protocolVersion": "2024-11-05"})
# Discover tools
tools = await mcp_call("http://localhost:8000/mcp", "tools/list")
# Ask
result = await mcp_call("http://localhost:8000/mcp", "tools/call", {
"name": "ask",
"arguments": {"query": "what's new this week?", "site": ["news"], "generate_mode": "summarize"}
})
```
### Wiring to Claude Code
Add an entry in `~/.claude.json` `mcpServers`:
```json
{
"mcpServers": {
"my-nlweb-site": {
"url": "http://localhost:8000/mcp",
"transport": "http"
}
}
}
```
(Verify the exact Claude Code MCP config schema in current docs — it changes.)
### Wiring to ChatGPT
ChatGPT Apps SDK requires the separate Node.js MCP server in `openai-apps-sdk-integration/nlweb_server_node/`. It bundles a React widget that renders the `nlweb-list` tool's results. Follow `docs/nlweb-chatgpt-integration.md` for the exact registration steps — ChatGPT's MCP app store rules change.
### Wiring to Gemini
Gemini's tool-calling supports MCP via the Vertex AI Agent SDK. Point it at `http://your-nlweb-host:8000/mcp` and call `tools/list` → `tools/call`.
### Gotchas
- The MCP wrapper's docstring **explicitly warns** that backwards compatibility is not guaranteed. Pin your client to the same NLWeb release you tested against, and re-verify `tools/list` on every upgrade.
- The `site` arg differs between `/ask` (string) and `/mcp::ask` (array). Don't confuse them.
- `/mcp` is **not SSE** by default. Don't wire your client expecting EventSource.
- The AppSDK adapter (port 8100) is its own thing — only ChatGPT Apps SDK clients should hit it; native MCP clients use port 8000's `/mcp`.
Always re-fetch `mcp_wrapper.py` and the chatgpt-integration doc before generating final code.Related Skills
mpp-server-middleware
Implement MPP server-side middleware for Hono, Express, Next.js, and Elysia. Use when protecting API routes with HTTP 402 payment gates, configuring payment methods, or setting up the Mppx server instance.
nlweb-tools-framework
Design and implement NLWeb tools — the per-Schema.org-type handlers that turn a query into a specialized response (search, item_details, compare_items, ensemble, recipe_substitution, accompaniment, conversation_search, etc.). Covers `tools.xml`, the ToolSelector router, builtin handlers in `methods/`, writing a custom tool with a `<returnStruc>` contract, and disabling tool selection for raw retrieval. Use when extending NLWeb beyond the default query → results flow.
nlweb-setup
Bootstrap a local NLWeb development environment from scratch — clone the repo, configure .env, install Python deps via `nlweb init-python`, run `nlweb init` for interactive LLM/retrieval selection, load sample Schema.org data, and verify with `nlweb check`. Use when starting a new NLWeb deployment from zero.
nlweb-schema-org-grounding
Prepare and structure site content as Schema.org JSON-LD for NLWeb ingestion — covers the supported types (Recipe, Product, Movie, Event, Article, RealEstate, Course, etc.), per-type behavior in NLWeb's tool routing, JSON-LD embedding patterns in HTML, sites.xml registration, and how the `schema_object` flows through ranking back to agent results. Use when authoring or auditing the structured data on a site that will be exposed via NLWeb.
nlweb-retrieval-backends
Choose and configure NLWeb retrieval backends — Qdrant (local + remote), Azure AI Search, Elasticsearch, OpenSearch (with/without k-NN), Postgres pgvector, Milvus, Snowflake Cortex Search, Cloudflare AutoRAG, Shopify MCP, and Bing Web Search. Covers `config_retrieval.yaml`, the single `write_endpoint` rule, parallel read-fanout with URL dedup, and per-backend setup pages. Use when picking a retrieval store, migrating between backends, or debugging "results are empty."
nlweb-prompts-customization
Customize NLWeb's LLM prompts and per-Schema.org-type behavior via `prompts.xml` and `site_types.xml` — covers the `<promptString>` template format, `<returnStruc>` JSON schemas, prompt inheritance, decontextualization/ranking/generate templates, per-site overrides, and pitfalls of editing prompts in place. Use when tuning answer quality, supporting a new domain, or localizing prompts.
nlweb-llm-providers
Configure NLWeb LLM and embedding providers — OpenAI, Azure OpenAI (default), Anthropic, Google Gemini, DeepSeek on Azure, Llama on Azure, HuggingFace, Inception Labs, Snowflake Cortex, Ollama, Pi Labs. Covers `config_llm.yaml` high/low tier model selection, the ModelRouter cost/quality routing logic, `config_embedding.yaml`, and adding a custom provider. Use when picking models, tuning cost, or wiring a new LLM backend.
nlweb-data-loading
Ingest site content into NLWeb's vector store using `db_load.py` — supports RSS/Atom feeds, Schema.org JSON-LD, sitemap-driven URL lists, and CSV. Covers chunking, embedding computation, site partitioning, batch sizing, delete-and-reload, and per-backend write_endpoint targeting. Use when bootstrapping a site's index, refreshing content, or migrating between retrieval backends.
nlweb-chatgpt-appsdk
Integrate NLWeb with ChatGPT's Apps SDK — the Node.js MCP server in `openai-apps-sdk-integration/`, the `nlweb-list` tool, the React widget at `ui://widget/nlweb-list.html`, and the port-8100 AppSDK adapter that translates NLWeb's message list to OpenAI Apps SDK envelopes. Use when publishing an NLWeb site as a ChatGPT app or wiring NLWeb results into an Apps SDK widget.
nlweb-auth-multitenancy
Configure NLWeb authentication and multi-tenant deployments — OAuth providers (GitHub, Google, Microsoft, Facebook), session storage, the `sites:` allowlist in `config_nlweb.yaml`, conversation persistence per authenticated user, and per-tenant data isolation. Use when adding login to an NLWeb instance, hosting multiple customers on one deployment, or persisting conversation history.
nlweb-ask-endpoint
Implement and consume the NLWeb /ask REST endpoint — request shape (GET/POST, query-string and v0.55 structured body), SSE streaming response, modes (list/summarize/generate), in-stream "message_type" headers, error envelopes, and client-side parsing. Use when building an NLWeb server route, calling /ask from a custom agent, or debugging /ask responses.
ap2-mcp-server
Implement AP2 MCP servers — payment tools exposed via Model Context Protocol for agent access to payment capabilities. Use when building MCP-based payment tool integrations for AP2.