The Build screen of the Voice AI console has three cards: Tools, Knowledge, and MCP servers. Tools bind to one agent_config. Knowledge sources and MCP servers do not — they are org-scoped catalogs backed by the knowledge_source and mcp_server tables and served by the adminKnowledge and adminMcp routers. This page covers the knowledge catalog and how the MCP catalog relates to the mcp-kind tool spec. For the tool spec shapes themselves, see Tool calling.

The three source kinds

A knowledge_source row carries a name, a kind, an optional description, and exactly one payload field determined by the kind. The console sends the same field set for every kind and lets the unused payload fields go out as null:
Writes go through adminKnowledge.create for a new source and adminKnowledge.update for an existing one.

Required fields by kind

The editor validates before it calls the mutation, so a malformed source never reaches the catalog: Because the file check falls back to the existing file_key, you can re-open a file source to change its name or description without re-uploading the blob.

Org-scoped catalog, not agent-bound

Tool mutations (admin.upsertAgentTool, admin.deleteAgentTool) look up the agent in the caller’s org, write to agent_tool keyed on (agent_id, name), and then call hydrateAndPublish so the change is live on the next call. Knowledge and MCP entries are different: they are addressed by orgId alone, and the adminKnowledge mutations the console calls do not republish an agent config. Editing a knowledge source is a catalog edit, not an agent deploy. Practically, that means the Knowledge card on the Build screen answers “what does this org have on file”, while the Tools card answers “what can this agent do mid-call”.

URL sources

For a url source, the console records the URL on the row and nothing else. The create / update bodies it sends carry only name, kind, description, and url — there is no refresh-interval, schedule, or crawl-depth field in the editor, and the screen surfaces no last-fetched timestamp. Fetching is handled outside the console; the catalog row is just the pointer. Keep the URL stable and publicly resolvable from TeleQuick’s side. If a document moves, edit the source rather than creating a second row with the same name.

File upload and storage

Self-hosted deployments store blobs in MinIO, not Supabase Storage, and only the BFF holds the root credentials. So the file does not go up with the tRPC mutation. The console:
  1. Creates (or updates) the knowledge_source row first, to obtain a sourceId.
  2. POSTs the blob as multipart/form-data to /api/knowledge/upload on the same origin.
  3. The BFF writes the object under <org>/<sourceId>/… and persists file_key on the row.
The upload is authenticated with the signed-in user’s Supabase session access token, not an API key:
The endpoint is considered successful only when the response is 2xx and the body has ok: true and a file_key. Anything else is reported in the modal as the returned error, or as Upload failed (HTTP <status>) when the body carries no message. The row-then-upload ordering is why a failed upload can leave a file source with no file_key: re-open it and pick the file again.

MCP server catalog vs per-tool MCP specs

There are two distinct MCP concepts on this screen, and they are not wired to each other in the shapes the console edits: An mcp-kind tool carries its own connection details in its spec, and the engine is the authority on that shape:
  • server_url — required, validated as a URL by the editor.
  • tool_name — the tool’s name on the server; defaults to the tool’s own name when omitted.
  • transport — http.
  • auth — written by the editor as { type: 'bearer', token } when you fill in the bearer token field, and removed from the spec when you clear it.
So adding a server to the org catalog does not by itself give an agent a tool, and an mcp tool does not reference a catalog entry by id — you still supply server_url on the tool. Treat the catalog as the org’s inventory of servers and the tool spec as the binding that the runtime actually calls.

Why a save fails

The Knowledge editor shows errors in two places: inline under the field that failed validation, and in the modal footer for anything the server or the upload returned.
  • Tool calling — the http, client, and mcp tool spec shapes and the silent flag
  • Authentication — API keys, relay tokens, and why the browser never holds a long-lived credential