Cograph
Cograph turns CSV files into queryable knowledge graphs. You ingest a CSV once, Cograph infers an ontology (types, attributes, relationships), and then you can ask natural-language questions that get translated to SPARQL and answered against the graph.
This skill teaches you how to use Cograph correctly. Follow it instead of guessing.
When to use this skill
Activate this skill when any of the following is true:
- The user mentions "cograph", "knowledge graph", "kg", or references a graph by name.
- The user wants to ask analytical questions about tabular data ("how many", "which has the most", "average price by…") and Cograph is configured in the environment.
- The user hands you a CSV and wants to query it rather than parse it cell-by-cell.
- The user wants to explore an ontology or list available graphs.
If the user just wants to read or transform a CSV row-by-row, this skill is not the right tool — use normal file tools.
Setup: wire up the MCP server
Cograph exposes its capabilities through an MCP server. Before you can call any tool, the server must be registered in the agent harness's MCP config (e.g. ~/.claude/mcp.json for Claude Code, the Cursor MCP settings panel, etc.):
{
"mcpServers": {
"cograph": {
"command": "python",
"args": ["-m", "omnix.mcp_server"],
"env": {
"OMNIX_API_URL": "http://localhost:8000",
"OMNIX_API_KEY": "dev-key-001"
}
}
}
}
If the cograph MCP server is not listed among your available tools, tell the user: "I don't see the Cograph MCP server registered. Add the config above to your MCP client and restart the session." Do not try to shell out to omnix or curl the REST API as a workaround unless the user explicitly asks — they may be on a machine without the CLI installed.
The six tools
All Cograph tool calls go through the cograph MCP server. There are exactly six tools. Know them.
1. list_knowledge_graphs
No parameters. Returns the name and description of every graph the current tenant can see.
When to call: Always call this first when you don't know which graph to query. Do not guess kg_name — guessing leads to "graph not found" errors that waste turns.
2. view_ontology
No parameters. Returns the full schema (types, attributes with datatypes, relationships between types) across all graphs for this tenant.
When to call: Before writing any non-trivial question, especially one that mentions a specific field ("price", "bedrooms", "city"). The ontology tells you the exact attribute names and types — using the ontology-aligned terms makes the natural-language translator dramatically more accurate.
3. ask
Parameters:
question(string, required) — the natural-language question.kg_name(string, optional) — target graph. Omit only if the user has already scoped the session to a single graph.
Returns an answer (human-readable string), the generated sparql, and an explanation. Show the user the answer by default; surface the sparql only if they ask how it was computed or the result looks wrong.
When to call: This is the main loop. Use it for any analytical question.
4. ingest_csv
Parameters:
file_path(string, required) — absolute path to the CSV on the machine running the MCP server.kg_name(string, required) — a new name for the graph. Use kebab-case (austin-zillow,events-sf-2026). If the user doesn't supply one, derive it from the filename and ask for confirmation before ingesting.
When to call: When the user gives you a new CSV and wants to query it. Schema is inferred automatically with a single LLM call against column headers + sample rows — do not pre-process the CSV yourself.
5. evolve_ontology
Parameters:
ask(string, required) — the schema change in plain English. You do not need to know the exact type, attribute, or relationship names. Describe the change the way a user would: "track which company a person works for", "record each product's release date", "link orders to the customer who placed them".knowledge_graph(string, optional) — target graph. Omit only if the session is already scoped to a single graph.
Returns a summary, the list of applied changes (high-confidence edits Cograph committed automatically), and any proposals (ambiguous or new-type changes that need your confirmation). Each change object looks like { kind: "attribute" | "relationship", subject_type, name, datatype_or_target, action: "reuse" | "extend" | "create", confidence, reason }.
When to call: When the user wants to add a new attribute, relationship, or type to an existing ontology and describes it in natural language. The resolver reuses existing types where it can — e.g. evolve_ontology(ask="track which company a person works for") reuses the existing Person type and adds a works_at relationship to Company, creating Company if it doesn't exist yet. Show the user the summary and the applied changes; if proposals came back, surface them and ask before applying.
6. apply_ontology_change
Parameters:
proposal(object, required) — one proposal object exactly as returned in theproposalsarray of anevolve_ontologycall. Pass it through unchanged.
Commits the proposed change. Stateless and idempotent — applying the same change twice is a no-op.
When to call: After evolve_ontology returns one or more proposals and the user confirms they want them. Apply one proposal per call. Do not hand-craft change objects — only pass back proposals the resolver produced.
The standard workflow
For almost every Cograph task, follow this sequence:
- Discover. Call
list_knowledge_graphs. If the target graph doesn't exist and you have a CSV, ingest it. If it doesn't exist and you don't have a CSV, stop and ask the user. - Orient. Call
view_ontologyand skim the types/attributes relevant to the user's question. This is cheap — do it even if you think you know the schema. - Ask. Call
askwith a question phrased using the ontology's attribute and type names. Passkg_nameexplicitly. - Report. Return the
answerto the user. If they asked a follow-up, reuse the same graph — do not re-run discovery unless something changed.
Skipping step 2 is the most common failure mode. Don't skip it.
Writing good questions for ask
The ask tool translates natural language to SPARQL using the ontology as context. You'll get better answers if you:
- Use the exact attribute names from
view_ontology. If the ontology calls itprice, say "price", not "cost". - Name the entity type explicitly. "How many
PropertyListingentities in Austin?" beats "How many are in Austin?". - Keep one question per call. Don't chain "X and also Y" — call
asktwice. - Be quantitative when possible. "Which category has the highest average price?" is easier than "What's interesting about categories?".
Ingesting CSVs safely
When the user hands you a new CSV:
- Confirm the absolute path — the MCP server runs on the user's machine and needs a path it can actually open.
- Propose a
kg_nameand confirm it with the user. Once ingested, the name sticks. - Call
ingest_csv. It may take several seconds for large files — this is normal. - After ingestion completes, call
view_ontologyso you can immediately see what Cograph inferred. Show the user a short summary ("Cograph detected aPropertyListingtype with attributes price, bedrooms, city…") before asking them what they want to know. - If the inferred ontology looks obviously wrong (e.g. a relationship was treated as a string attribute), tell the user — don't silently query broken data.
Do not ingest the same CSV twice under different names "just in case". Do not re-ingest to "refresh" unless the file actually changed.
Failure recovery
list_knowledge_graphsreturns an empty list: The tenant has no data yet. Ask the user to provide a CSV.askreturns an empty or zero answer: Don't assume there's no data. Callview_ontology(if you haven't) and check whether you used the right attribute names. Retry once with corrected terminology. If still empty, tell the user and suggest a broader question.askraises a SPARQL error: Usually means the question referenced a field the ontology doesn't have. Re-read the ontology and rephrase.ingest_csvfails: Check that the path is absolute and the file exists. If it does, report the error to the user verbatim — it's likely a server-side issue they need to see.- The MCP server isn't available: See the setup section. Do not fall back to writing SPARQL by hand against an unknown endpoint.
What Cograph is not
- Not a row lookup tool. Don't use
askto fetch individual records by ID — read the CSV directly if that's what the user wants. - Not a data write API. There is no "update this entity" tool — re-ingest if the source data changed. (You can evolve the schema in plain English with
evolve_ontology, but that changes types/attributes/relationships, not individual records.) - Not multi-graph join-aware.
askoperates on one graph at a time. If the user wants to combine graphs, run two asks and combine the answers yourself.
Quick reference
| Situation | Tool |
|---|---|
| "What graphs do I have?" | list_knowledge_graphs |
| "What's in this graph?" / "What fields are there?" | view_ontology |
| Any analytical question about the data | ask |
| New CSV the user wants to query | ingest_csv → view_ontology → ask |
| "Track / record / link …" (a new field, relationship, or type, in plain English) | evolve_ontology |
Confirm a proposal returned by evolve_ontology | apply_ontology_change |
When in doubt: discover, orient, ask.