Both go in the session’s
tools, and you can mix them.
Function tools
A function tool is the OpenAI Realtime format: a name, a description and a JSON schema for the arguments.response.function_call_arguments.done with a
call_id, name and arguments. Run it, then send the result and ask Nur to
go on:
Remote MCP servers
Point the session at an MCP server and Nur can use its tools while it talks. EESI lists the server’s tools, offers them to Nur, runs the calls she makes and puts the results back into the conversation. Your app does not handle the calls.What happens
- Your
session.updatetakes effect at once. The server’s tools are listed in the background, so nothing waits on a slow server. - You get
mcp_list_tools.in_progress, thenmcp_list_tools.completed(ormcp_list_tools.failed). Aconversation.item.donewith anmcp_list_toolsitem lists the tools Nur was given. If your first question needs the tools, wait forcompletedbefore you ask it. - Nur sees each tool as a function named
<server_label>__<tool>, for exampledeepwiki__ask_wiki_question. - When Nur calls one, you see an
mcp_callitem (inresponse.output_item.addedandresponse.done), thenresponse.mcp_call.in_progress, thenresponse.mcp_call.completedorresponse.mcp_call.failed. Aconversation.item.donecarries themcp_callitem with itsoutput, or itserror. - Nur reads the result and keeps talking. You don’t send anything back.
Asking first
A tool the server marks as destructive (destructiveHint in its MCP
annotations) never runs on Nur’s word alone. Neither does a tool you list in
require_approval. The first time Nur calls it, she asks the person instead,
and you get an mcp_approval_request item:
require_approval: "never" cannot switch
this off for a tool the server marks as destructive.
When others can be heard, on a call or a speakerphone, a yes said in the room
may not be the person’s. Set eesi_spoken_approvals to false and only your
app’s mcp_approval_response answers: nothing said or typed in the
conversation does, and Nur asks the person to answer on their screen. It can
change in any session.update; true, the default, lets their words answer
again.
invalid_value error, and until you send
true or false only your app’s answer counts.
Per reply
response.create may carry its own tools. An MCP entry there names one of
the session’s servers by its server_label and stands for that server’s tools;
declare servers on the session. A tool_choice of
{"type": "mcp", "server_label": "deepwiki", "name": "ask_wiki_question"}
names that tool, the way a function tool_choice names a function.
Limits
Security
- The server must be on the public internet over
https. Addresses that point to private networks or cloud metadata services are refused, and so are redirects. authorizationandheadersare sent to that server and nowhere else. They are not logged and not echoed back to you.- Results are third-party content, and Nur is told so: they reach her as the server’s words, not hers and not yours.
With client secrets
A server can be part of a client secret. Minting checks it, and the response showsauthorization and headers as
[redacted]. With tools locked (the default), the device cannot add, change
or remove servers, in session.update or in a reply’s own tools. The person
can still approve or decline a tool, since that is their answer to Nur.