Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 29 additions & 23 deletions NLWEBSPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Example:
{
"prefer": {
"streaming": false,
"response_format": "chatgpt_app",
"response_format": "mcp_app",
"mode": "list, summarize",
"accept-language": "en",
"user-agent": "Copilot/1.0.0"
Expand All @@ -124,7 +124,7 @@ Example:
We expect a wide range of clients to call NLWeb agents — from chatbots to site search interfaces to data analytics tools. Different output structures may be suitable for different clients. The set of possible response_format values is open-ended and extensible. This specification defines two formats:

* conversational_search (default): Returns results in the Conversational Search result structure (see 4.1.1).
* chatgpt_app: Returns results in the ChatGPT App result structure (see 4.1.1), conforming to the ChatGPT Apps SDK.
* mcp_app: Returns results in the MCP Apps result structure (see 4.1.1), conforming to the MCP Apps extension ([io.modelcontextprotocol/ui](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx)).

NLWeb agents may support additional formats. A client may specify the formats it can accept, and the NLWeb agent chooses the best match.

Expand Down Expand Up @@ -187,12 +187,12 @@ Convention: Request metadata uses the attribute name meta. Response metadata use
Metadata about the response.

* response_type (string, required): One of "answer", "elicitation", "promise", or "failure".
* response_format (string, optional): The response format of the answer (e.g., "conversational_search", "chatgpt_app").
* response_format (string, optional): The response format of the answer (e.g., "conversational_search", "mcp_app").
* version (string, required): API version number.
* session_context (object, optional): Context object which can include attribute-value pairs that need to be included in future calls to the NLWeb agent.
* Response format-specific fields such as:
* openai/outputTemplate (string): For ChatGPT Apps SDK — URI of the widget template.
* openai/widgetAccessible (boolean): For ChatGPT Apps SDK — whether the widget can make tool calls.
* ui (object): For the MCP Apps extension. Associates the result with a UI resource used to render it. Contains:
* resourceUri (string): URI of the UI resource (the rendering template), using the `ui://` scheme (e.g., "ui://recipe-server/recipe-widget"). Over MCP transport, the host retrieves the template via `resources/read`. Over HTTP transport, the URI MUST be resolvable by the client to a UI resource served as `text/html;profile=mcp-app`.
* Other protocol-specific metadata as needed.

### 4.1 Response Content
Expand All @@ -201,7 +201,7 @@ The result structure is a function of the response_type. The following subsectio

#### 4.1.1 Answer

Though we expect to allow different structures for the content, as specified by the response_format in the request, we expect most answers to be an array of JSON objects, each encoding some semi-structured information. In some cases, as with ChatGPT apps, the structured and unstructured portions may be broken out into separate sections.
Though we expect to allow different structures for the content, as specified by the response_format in the request, we expect most answers to be an array of JSON objects, each encoding some semi-structured information. In some cases, as with MCP Apps, the structured and unstructured portions may be broken out into separate sections.

This specification defines two result structures.

Expand Down Expand Up @@ -246,41 +246,46 @@ Example:
}
```

**ChatGPT App Result Structure**
**MCP Apps Result Structure**

This structure conforms to the structure specified for ChatGPT apps. The main differences from Conversational Search are:
This structure conforms to the MCP Apps extension ([io.modelcontextprotocol/ui](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx)), which standardizes how a result is paired with an interactive UI. The main differences from Conversational Search are:

1. content (array, required): Used for natural language descriptions of the result, meant for consumption by the chatbot's LLM. An array of JSON objects, each with:
1. content (array, required): Used for natural language descriptions of the result, meant for consumption by the host's model and by text-only hosts. An array of JSON objects, each with:
* type (string): The value "text".
* text (string): A natural language description of the results.

2. structuredData (array, required): An array of typed semi-structured JSON objects, following the same item schema as results in the Conversational Search structure.
2. structuredContent (object, required): Structured data optimized for UI rendering (and not added to the model's context). NLWeb places the typed semi-structured items under a results array, where each item follows the same item schema as results in the Conversational Search structure.

The UI resource used to render the result is referenced from `_meta.ui.resourceUri` (see the _meta section above).

Example:
```json
{
"_meta": {
"response_type": "answer",
"response_format": "chatgpt_app",
"response_format": "mcp_app",
"version": "0.55",
"openai/outputTemplate": "https://example.com/recipe-widget",
"openai/widgetAccessible": true
"ui": {
"resourceUri": "ui://recipe-server/recipe-widget"
}
},
"content": [
{
"type": "text",
"text": "Here are protein-rich pumpkin recipes with cinnamon..."
}
],
"structuredData": [
{
"@type": "Recipe",
"name": "Pumpkin spice with coconut",
"description": "....",
"recipeIngredient": ["..."],
"cookTime": "PT30M"
}
]
"structuredContent": {
"results": [
{
"@type": "Recipe",
"name": "Pumpkin spice with coconut",
"description": "....",
"recipeIngredient": ["..."],
"cookTime": "PT30M"
}
]
}
}
```

Expand Down Expand Up @@ -1033,7 +1038,8 @@ Checking on the promise with await:
* Elicitation question types enumerated: single_select, multi_select, free_text, number, boolean.
* Error codes enumerated: NO_RESULTS, INVALID_QUERY, UNSUPPORTED_FORMAT, UNSUPPORTED_MODE, RATE_LIMITED, INTERNAL_ERROR, TIMEOUT, TOKEN_LIMIT.
* Summary items in Conversational Search results given a recommended @type of SearchSummary.
* response_format values documented: conversational_search (default) and chatgpt_app.
* response_format values documented: conversational_search (default) and mcp_app.
* Interactive UI output migrated from the ChatGPT Apps SDK structure to the MCP Apps extension (io.modelcontextprotocol/ui): response_format chatgpt_app replaced by mcp_app, structuredData (array) replaced by structuredContent (object with a results array), and the openai/outputTemplate and openai/widgetAccessible meta fields replaced by _meta.ui.resourceUri referencing a ui:// resource.
* User object in meta clarified as accepting either a string or structured object.
* Authentication, authorization, and rate limiting explicitly scoped as transport-layer concerns (Sections 2.4, 2.5).
* HTTP status code guidance added (Section 7.4).
Expand Down
52 changes: 29 additions & 23 deletions app/docs/specification/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Example:
{
"prefer": {
"streaming": false,
"response_format": "chatgpt_app",
"response_format": "mcp_app",
"mode": "list, summarize",
"accept-language": "en",
"user-agent": "Copilot/1.0.0"
Expand All @@ -124,7 +124,7 @@ Example:
We expect a wide range of clients to call NLWeb agents — from chatbots to site search interfaces to data analytics tools. Different output structures may be suitable for different clients. The set of possible response_format values is open-ended and extensible. This specification defines two formats:

* conversational_search (default): Returns results in the Conversational Search result structure (see 4.1.1).
* chatgpt_app: Returns results in the ChatGPT App result structure (see 4.1.1), conforming to the ChatGPT Apps SDK.
* mcp_app: Returns results in the MCP Apps result structure (see 4.1.1), conforming to the MCP Apps extension ([io.modelcontextprotocol/ui](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx)).

NLWeb agents may support additional formats. A client may specify the formats it can accept, and the NLWeb agent chooses the best match.

Expand Down Expand Up @@ -187,12 +187,12 @@ Convention: Request metadata uses the attribute name meta. Response metadata use
Metadata about the response.

* response_type (string, required): One of "answer", "elicitation", "promise", or "failure".
* response_format (string, optional): The response format of the answer (e.g., "conversational_search", "chatgpt_app").
* response_format (string, optional): The response format of the answer (e.g., "conversational_search", "mcp_app").
* version (string, required): API version number.
* session_context (object, optional): Context object which can include attribute-value pairs that need to be included in future calls to the NLWeb agent.
* Response format-specific fields such as:
* openai/outputTemplate (string): For ChatGPT Apps SDK — URI of the widget template.
* openai/widgetAccessible (boolean): For ChatGPT Apps SDK — whether the widget can make tool calls.
* ui (object): For the MCP Apps extension. Associates the result with a UI resource used to render it. Contains:
* resourceUri (string): URI of the UI resource (the rendering template), using the `ui://` scheme (e.g., "ui://recipe-server/recipe-widget"). Over MCP transport, the host retrieves the template via `resources/read`. Over HTTP transport, the URI MUST be resolvable by the client to a UI resource served as `text/html;profile=mcp-app`.
* Other protocol-specific metadata as needed.

### 4.1 Response Content
Expand All @@ -201,7 +201,7 @@ The result structure is a function of the response_type. The following subsectio

#### 4.1.1 Answer

Though we expect to allow different structures for the content, as specified by the response_format in the request, we expect most answers to be an array of JSON objects, each encoding some semi-structured information. In some cases, as with ChatGPT apps, the structured and unstructured portions may be broken out into separate sections.
Though we expect to allow different structures for the content, as specified by the response_format in the request, we expect most answers to be an array of JSON objects, each encoding some semi-structured information. In some cases, as with MCP Apps, the structured and unstructured portions may be broken out into separate sections.

This specification defines two result structures.

Expand Down Expand Up @@ -246,41 +246,46 @@ Example:
}
```

**ChatGPT App Result Structure**
**MCP Apps Result Structure**

This structure conforms to the structure specified for ChatGPT apps. The main differences from Conversational Search are:
This structure conforms to the MCP Apps extension ([io.modelcontextprotocol/ui](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx)), which standardizes how a result is paired with an interactive UI. The main differences from Conversational Search are:

1. content (array, required): Used for natural language descriptions of the result, meant for consumption by the chatbot's LLM. An array of JSON objects, each with:
1. content (array, required): Used for natural language descriptions of the result, meant for consumption by the host's model and by text-only hosts. An array of JSON objects, each with:
* type (string): The value "text".
* text (string): A natural language description of the results.

2. structuredData (array, required): An array of typed semi-structured JSON objects, following the same item schema as results in the Conversational Search structure.
2. structuredContent (object, required): Structured data optimized for UI rendering (and not added to the model's context). NLWeb places the typed semi-structured items under a results array, where each item follows the same item schema as results in the Conversational Search structure.

The UI resource used to render the result is referenced from `_meta.ui.resourceUri` (see the _meta section above).

Example:
```json
{
"_meta": {
"response_type": "answer",
"response_format": "chatgpt_app",
"response_format": "mcp_app",
"version": "0.55",
"openai/outputTemplate": "https://example.com/recipe-widget",
"openai/widgetAccessible": true
"ui": {
"resourceUri": "ui://recipe-server/recipe-widget"
}
},
"content": [
{
"type": "text",
"text": "Here are protein-rich pumpkin recipes with cinnamon..."
}
],
"structuredData": [
{
"@type": "Recipe",
"name": "Pumpkin spice with coconut",
"description": "....",
"recipeIngredient": ["..."],
"cookTime": "PT30M"
}
]
"structuredContent": {
"results": [
{
"@type": "Recipe",
"name": "Pumpkin spice with coconut",
"description": "....",
"recipeIngredient": ["..."],
"cookTime": "PT30M"
}
]
}
}
```

Expand Down Expand Up @@ -1033,7 +1038,8 @@ Checking on the promise with await:
* Elicitation question types enumerated: single_select, multi_select, free_text, number, boolean.
* Error codes enumerated: NO_RESULTS, INVALID_QUERY, UNSUPPORTED_FORMAT, UNSUPPORTED_MODE, RATE_LIMITED, INTERNAL_ERROR, TIMEOUT, TOKEN_LIMIT.
* Summary items in Conversational Search results given a recommended @type of SearchSummary.
* response_format values documented: conversational_search (default) and chatgpt_app.
* response_format values documented: conversational_search (default) and mcp_app.
* Interactive UI output migrated from the ChatGPT Apps SDK structure to the MCP Apps extension (io.modelcontextprotocol/ui): response_format chatgpt_app replaced by mcp_app, structuredData (array) replaced by structuredContent (object with a results array), and the openai/outputTemplate and openai/widgetAccessible meta fields replaced by _meta.ui.resourceUri referencing a ui:// resource.
* User object in meta clarified as accepting either a string or structured object.
* Authentication, authorization, and rate limiting explicitly scoped as transport-layer concerns (Sections 2.4, 2.5).
* HTTP status code guidance added (Section 7.4).
Expand Down
Loading