MCP
Fontana Knowledge Graph exposes agent retrieval as a first-party Model Context Protocol server on your tenant origin at /_kg-engine/mcp (Streamable HTTP). Agents explore through an evidence loop: search or open a chunk, read its position, section, entities and neighbours in the same payload, then hop to more chunks. Every answer contains only what the caller may read (Permissions). Enable the seeded Knowledge Graph connection on agents you assign namespaces to.
The engine resolves the caller's namespace allow-list from Convex on every call and fails closed: missing or unresolvable caller context returns an empty result with an explicit auth error, never a cross-namespace answer.
Tool catalog
Section titled “Tool catalog”| Tool | What it does |
|---|---|
kg_search |
Hybrid search (full-text, vector, graph expansion) fused with RRF; several namespaces fuse by rank. Returns capped chunk packages. Disabled and unreadable content is excluded. |
kg_open |
Open packages by exactly one of chunkKey, outlineKey (that section’s chunks), entityKey (chunks mentioning it), or fileId (the file’s chunks in order). |
kg_hop |
Typed hop onto related packages: next_chunk, prev_chunk, similar (from a chunkKey); mentions, rel, same_type (from an entityKey); outline_child, outline_parent, outline_siblings (from an outlineKey). |
kg_outline |
A file’s page index: sections in document order with outlineKey, title, depth, parent and pages. Paged with cursor / nextCursor; limit maxDepth for large files. |
kg_ontology |
Published TBox for a namespace (entity types, relation types, PATTERN endpoints). |
kg_entity_search |
Named-entity entry by text and/or vector similarity; returns type labels and mention evidence packages. |
kg_file_entities |
File-scoped entity inventory: all entities mentioned by the file’s chunks plus published entity types used in that file. Paginate with afterEntityKey when truncated. |
kg_file_triples |
File-scoped instance REL triples where both subject and object are mentioned in the file. |
kg_namespaces |
List Knowledge Graph namespaces the caller may read. |
kg_files |
Find files in one namespace by path. folderPrefix and name (a path glob) combine. Lists a page (cursor / nextCursor). Each file includes namespace, path, and fileId (file: plus the path). |
kg_file |
Describe one file: namespace plus path or fileId returns size, mime, and status; a csv or tsv also returns columns. Contents and queries are Fontana Files. See Read or query a file. |
kg_cypher |
One read-only OpenCypher statement for an exact word, a figure, or a known path (at most 50 rows, 2 second limit). Return the file path and the chunk text. An entity name alone is not a citation. A misspelling is entity search, then a walk from the resolved name. |
Enable these tools on an agent with the Knowledge capability tile on the agent card.
Chunk packages
Section titled “Chunk packages”Every search, open, hop, and entity-search hit is a chunk package. Lists carry truncated and total when clipped at the requested cap.
| Field | Contents |
|---|---|
text |
The chunk text, plus contextHeader (the “Document › Heading › Subheading” trail) and citation (namespace/path › sections (pp.)) |
position |
chunkIndex, charStart / charEnd in the parsed text, page and line span, tokenCount, prevChunkKey, nextChunkKey |
outline |
The chunk’s page-index section: outlineKey, title, depth, order, and its ancestors, siblings and children |
mentions |
Entities the chunk mentions: key, name, type id and label, how it was found (method), and the quoted text |
relNeighbors |
Typed relations of those entities, when a file you may read states them |
dates |
The file’s documentDate, effective window and collections |
similarFiles |
Readable files similar to the chunk’s file, best first |
| Cap | Default | Hard max |
|---|---|---|
topK |
8 | 32 |
mentions |
8 | 24 |
rel |
8 | 24 |
ancestors |
6 | 12 |
siblings |
8 | 24 |
children |
8 | 24 |
similar |
4 | 16 |
Pass caps on the tool call to override defaults. Values over the hard max fail closed with an error. Optional tokenBudget omits or truncates chunk text. Files ingested before character offsets existed report trace.missingOffsets until they are reprocessed.
Hybrid search (kg_search)
Section titled “Hybrid search (kg_search)”kg_search runs one or more retrieval lanes and fuses results with reciprocal rank fusion (RRF):
| Parameter | Default | Purpose |
|---|---|---|
query |
(required) | Search text |
namespaces |
All allowed | Subset of the caller’s namespace allow-list |
lanes |
fulltext, vector, graph_expand |
Which lanes to run. co_annotation is opt-in and is not in the default. A failed lane soft-fails empty without aborting the whole search |
tokenBudget |
none | Estimated token cap on returned chunk text |
filters |
none | Collection, folder, temporal, and relation filters |
ranking.rrfK |
60 | RRF constant k |
ranking.laneWeights |
1 each | Per-lane multipliers on RRF contributions |
ranking.minScore |
none | Drop hits below this display score (0–1 scale) |
Across several namespaces, results interleave by rank within each namespace, not by raw score: scores from different corpora are not comparable. Multi-namespace search keeps per-namespace and per-lane soft-fail: empty the failed lane or namespace, continue others, never abort the agent turn.
When filters or disabled files hide most of a namespace, the vector lane widens its candidate pool in rounds instead of returning fewer hits; trace.vectorWidening reports the final pool and whether its cap was reached.
Co-annotation lane
Section titled “Co-annotation lane”The assistant includes co_annotation in lanes when it wants chunks that mention two entities named in the question. That lane stays off unless the search asks for it. Studio search has no switch for it. People asking in chat do not set this argument.
The span linker runs only when co-annotation is on. It attaches a phrase in the question to a nearby entity when the published ontology did not already name it.
Grounding roles on the response label those entities from how often they are mentioned. The pipeline diagram stays the ingest stages in Processing lanes.
When the lane runs, the response includes grounding, one entry per namespace. Each entry lists the grounded entities with their roles, the chosen pair, directCount (chunks that mention both entities), and bridgeCount (chunks one relation away). When the lane cannot form that evidence, the entry carries a reason such as too_few_bridges.
Open, hop, ontology, entities
Section titled “Open, hop, ontology, entities”kg_open: Resolve one key to packages when you already have a chunk, outline, entity, or file id.kg_hop: Expand fromfromKeywith a typedkind.similarmoves to the first chunks of files similar to the chunk’s file.kg_outline: Read a file’s table of contents, then open a section withkg_open {outlineKey}.kg_ontology: Fetch the published type box when you need TBox without stuffing it onto every search hit.kg_entity_search: Start from a name; results still land on mention packages so answers stay citation-backed. Each hit carriesdegree(how many chunks mention the entity) androle:bridge(specific enough to connect the question to evidence),filter(common enough to narrow the question, not to connect chunks), orignore(too common to connect the question to evidence).kg_file_entities: List entities and entity types already extracted for one file before you edit them or re-run an ontology review. UseafterEntityKeywhen the response istruncated.kg_file_triples: List typed REL instance triples for one file when both endpoints are mentioned in that file. Whentruncatedis true, passcontinueAfterback asafterSourceEntityKey,afterRelationTypeId, andafterTargetEntityKey.
Read or query a file
Section titled “Read or query a file”Every hit names a file: a search package, kg_open, kg_files and kg_file all carry namespace, path, and fileId. fileId is file: plus path. Chat @kg:<namespace>/<path> maps to that namespace and path.
kg_file describes the file: size, mime type, and status, and for a csv or tsv the columns (header names). Reading and querying the file is the Fontana Files MCP, on the same tenant with the same credentials: pass namespace and the same path or fileId, unchanged, to get_file or query. file:notes/a.txt and notes/a.txt are the same file.
| Need | Fontana Files call |
|---|---|
| The text | get_file with namespace and path |
| A line window | query with type: "text", startLine, endLine |
| An in-file or folder regex | query with type: "grep"; a path ending in / searches that folder; a hit returns path and fileId |
| SQL over a csv, tsv, json, or jsonl | query with type: "sql"; the table is the quoted path: SELECT * FROM "sales.csv". Quote a header that is not a bare name: "Market Value (AUD)" |
| JSON | query with type: "jsonpath", "jsonata", or "jinja" (Jinja receives the parsed document as data) |
In Flow, the Files ability gives an agent these tools as mcp_ffs_get_file and mcp_ffs_query, next to the Knowledge ability’s mcp_knowledge-graph_* tools.
OpenCypher (kg_cypher)
Section titled “OpenCypher (kg_cypher)”kg_cypher runs one read-only OpenCypher statement against a single namespace. Label every node, follow one relationship at a time, project a property such as f.vfsPath, and end with a literal LIMIT from 1 to 50. The platform stops each query after 2 seconds. Parallel calls wait in line, and Falkor still runs one of these statements at a time.
List the namespaces you may read with kg_namespaces, and read a namespace’s published type box with kg_ontology, before you write a statement. The namespace argument selects the graph. Node labels are Chunk, FileRef, Entity, and EntityType. To read the next page, add WHERE ID(n) > $afterId. SKIP is rejected.
The graph stores:
- FileRef, a file (
vfsPath,name,fileId). A Folder (folderPath) connects withFolder -[:HAS_CHILD]-> FileRef. - Chunk, one text window (
text,path,chunkIndex).Chunk -[:PART_OF]-> FileRefandChunk -[:NEXT_CHUNK]-> Chunk. - OutlineNode, a heading (
title).OutlineNode -[:COVERS]-> Chunk. - Entity, a mention (
name,typeId). OnlyChunk -[:MENTIONS]-> Entity. - EntityType, the published schema (
typeId,label,side = "published"). - REL, a typed link between entities (
relationTypeId), when the namespace has any. Start from a chunk mention and alias the edge.
An entity, heading, or folder has to share the pattern with an aliased Chunk or FileRef. An exact word in a known path:
MATCH (c:Chunk)-[:PART_OF]->(f:FileRef)WHERE toLower(c.text) CONTAINS "dkim" AND f.vfsPath CONTAINS "reports"RETURN f.vfsPath AS path, c.text AS textLIMIT 10An answer cites the file path and the chunk text it came from. An entity name on its own is not a source. Cypher matches the text it is given: a misspelling such as “remed” for “Resmed” is an entity search, then a Cypher walk from that name back to the mentioning chunk. To connect two files, follow Chunk -[:MENTIONS]-> Entity <-[:MENTIONS]- Chunk and return each file path.
kg_search answers by meaning when you do not know the words or the path. Cypher answers an exact word, a figure, or a known path. The namespace argument has to be one your namespace grants let you read, and the platform injects the enabled-file check and any pinned filters onto each aliased Chunk and FileRef before the query runs.
Permissions, fail closed
Section titled “Permissions, fail closed”Every KG tool call is permission-enforced. Fontana resolves the caller’s readable namespaces from the namespace grants on each call. Nothing from a namespace the caller may not read, or from a disabled file, reaches the answer: not its chunks, not the entities only it mentions, not relations only it states, not its similar-file links. If the caller context is missing or cannot be resolved, the call fails closed: an explicit auth error, never a silent empty result or a cross-namespace answer.
In-app agents and external PAT clients both execute tools under your identity. An in-app agent reads only the namespaces on its allow-list that you may read.
Using Knowledge Graph MCP in Flow
Section titled “Using Knowledge Graph MCP in Flow”- Agents: enable the seeded Knowledge Graph MCP connection from AI → Tools and assign namespaces on the agent (Knowledge capability tile).
- Chat: when the Knowledge Graph toggle is on, qualifying search evidence may be injected into the turn automatically. An answer that uses a file shows a bookmark for that file. Hover the bookmark to see the namespace and path. Click it to open the file in Knowledge Graph.
- KG Studio: graph layout, ontology editing, and search debugging use the product UI against the same tenant data plane.
Memory writes use knowledge_addMemory and knowledge_forgetMemory, not MCP. Every agent has both without setup. Each user has one private memory store in Fontana Files, shared by the agents that user runs. Its files are searchable like any other namespace you can read, so Knowledge Graph search returns your memories next to other evidence. See agent memory for paths, overwrite, and the Forget memory button in chat.
Your conversations are a private namespace too: every completed turn is saved to your threads namespace in Fontana Files and indexed like any other document. Your own searches reach it. An agent turn reaches it only in a chat of your own, never in a shared conversation, a Slack or Teams thread, a schedule, an evaluation run, or Knowledge Graph extraction, and naming the namespace in a tool call does not change that. See where conversations are saved.
Tenant endpoints
Section titled “Tenant endpoints”On your tenant Flow origin:
- Health:
https://<tenant>.<baseDomain>/_kg-engine/health(no auth) - MCP (Streamable HTTP):
https://<tenant>.<baseDomain>/_kg-engine/mcp
In Flow: enable the seeded Knowledge Graph connection on an agent from AI → Tools. Flow runs tool calls as the signed-in user.
External MCP clients (Cursor, ChatGPT)
Section titled “External MCP clients (Cursor, ChatGPT)”Use a personal access token (PAT) to connect external MCP clients to your tenant’s public /_kg-engine/mcp endpoint. PATs authenticate as you; knowledge-graph:read and your namespace grants apply exactly as for in-app agents.
On AI → Tools, select the seeded Knowledge Graph MCP. Flow shows copyable URL, Authorization header, and Cursor JSON for ChatGPT, Claude, Cursor, and other Streamable HTTP clients. Create a PAT under Admin → Personal access tokens and paste the full fnt_pat_… value into your client config.
Issue a PAT
Section titled “Issue a PAT”- Sign in to your tenant Flow origin (the same HTTPS hostname you use for workflows, for example
https://acme.example.com). - Open Admin → Personal access tokens (
/admin/access-tokens). - Select Create PAT, then copy the full token (
fnt_pat_…). It is shown once; store it in a password manager. - Rotate or revoke at the same page if the token is exposed.
The PAT must be minted on the same tenant origin you configure in your MCP client. A token from one hostname does not work on another.
Cursor
Section titled “Cursor”Add a Streamable HTTP server in your Cursor MCP configuration (~/.cursor/mcp.json or a project-level .cursor/mcp.json):
{ "mcpServers": { "knowledge-graph": { "url": "https://<tenant>.<baseDomain>/_kg-engine/mcp", "headers": { "Authorization": "Bearer fnt_pat_…" } } }}After editing MCP config, run Developer: Reload Window in Cursor (or fully quit and reopen).
ChatGPT (Developer mode)
Section titled “ChatGPT (Developer mode)”ChatGPT connects to remote HTTPS MCP servers only (Streamable HTTP). You need a paid plan with Developer mode enabled (Settings → Security and login).
- Open Settings → Apps & Connectors (or ChatGPT Plugins → + in newer UI).
- Create a custom connector (Developer mode):
- Connector URL:
https://<tenant>.<baseDomain>/_kg-engine/mcp - Authentication: Token (not OAuth), or a single
Authorizationheader (see below).
- Connector URL:
- Paste your full
fnt_pat_…value. ChatGPT sendsAuthorization: Bearer fnt_pat_…to your tenant MCP endpoint.
Header-only setup (works in Cursor and ChatGPT):
| Field | Value |
|---|---|
| URL | https://<tenant>.<baseDomain>/_kg-engine/mcp |
| Bearer token env var | (leave empty unless you set the env var on the host) |
| Header name | Authorization |
| Header value | Bearer fnt_pat_… (full token, including the Bearer prefix) |
Env-var setup (ChatGPT desktop / Codex): set bearer_token_env_var to a name such as MCP_PAT, export that variable to the raw token (no Bearer prefix), and do not also send a conflicting Authorization header.
Verify PAT auth
Section titled “Verify PAT auth”Health checks do not use auth. Confirm the PAT on the MCP path:
export MCP_PAT='fnt_pat_…' # full token from /admin/access-tokens
curl -fsS "https://<tenant>.<baseDomain>/_kg-engine/health"# {"ok":true}
curl -sS -w "\nHTTP %{http_code}\n" -X POST \ -H "Authorization: Bearer $MCP_PAT" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' \ "https://<tenant>.<baseDomain>/_kg-engine/mcp"Replace <tenant>.<baseDomain> with your tenant origin. 401 means the token is missing, truncated, revoked, or minted on a different origin. 200 with a JSON-RPC body means auth succeeded.
Troubleshooting 401
Section titled “Troubleshooting 401”| Symptom | Likely cause | Fix |
|---|---|---|
| Health OK, MCP 401 | Bad or missing Authorization |
Use Authorization: Bearer fnt_pat_… only; pick one auth method (header or env var, not both) |
| Intermittent 401 | Bearer env var and header both set | Pick one auth method; clear the other |
| Always 401 | Truncated token in the UI | Re-copy the full PAT (~50+ characters after fnt_pat_) |
| Always 401 | PAT from another tenant origin | Create the PAT on the same hostname as your MCP client URL |
| Always 401 | Revoked or rotated PAT | Create a new PAT at /admin/access-tokens |