A relay session: an AI assistant builds an OWL ontology from scratch using only MCP tool calls. SVGs and tool results are generated by
scripts/run-demo.mjsagainst a live dev server. Do not edit the rendered file (docs/mcp-demo/reasoning-demo.md) — edit this seed instead, then regenerate:node scripts/run-demo.mjs docs/mcp-demo/seeds/reasoning-demo.md
You: I want to model a small organisation in OWL. Let's start with a four-level class hierarchy: Person → Employee → Manager → Executive. Then we'll add properties, individuals, and run the reasoner.
Assistant: I'll build this in phases — classes first, then properties, then individuals, then axioms. Starting in TBox view so every class and property node lands on the right canvas.
5 tool calls ✓
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"setViewMode","arguments":{"mode":"tbox"}}}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#Person","typeIri":"http://www.w3.org/2002/07/owl#Class","label":"Person"}}}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#Employee","typeIri":"http://www.w3.org/2002/07/owl#Class","label":"Employee"}}}
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#Manager","typeIri":"http://www.w3.org/2002/07/owl#Class","label":"Manager"}}}
{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#Executive","typeIri":"http://www.w3.org/2002/07/owl#Class","label":"Executive"}}}
[Ontosphere — 5 tools ✓]
✓ setViewMode
✓ addNode: http://example.com/reasoning-demo#Person
✓ addNode: http://example.com/reasoning-demo#Employee
✓ addNode: http://example.com/reasoning-demo#Manager
✓ addNode: http://example.com/reasoning-demo#Executive
Canvas: 4 nodes, 0 links
Assistant: All four classes are on canvas. Now the six property nodes:
6 tool calls ✓
{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#knows","typeIri":"http://www.w3.org/2002/07/owl#ObjectProperty","label":"knows"}}}
{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#hasFriend","typeIri":"http://www.w3.org/2002/07/owl#ObjectProperty","label":"hasFriend"}}}
{"jsonrpc":"2.0","id":8,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#manages","typeIri":"http://www.w3.org/2002/07/owl#ObjectProperty","label":"manages"}}}
{"jsonrpc":"2.0","id":9,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#isManagedBy","typeIri":"http://www.w3.org/2002/07/owl#ObjectProperty","label":"isManagedBy"}}}
{"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#isColleagueOf","typeIri":"http://www.w3.org/2002/07/owl#ObjectProperty","label":"isColleagueOf"}}}
{"jsonrpc":"2.0","id":11,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#hasSupervisor","typeIri":"http://www.w3.org/2002/07/owl#ObjectProperty","label":"hasSupervisor"}}}
[Ontosphere — 6 tools ✓]
✓ addNode: http://example.com/reasoning-demo#knows
✓ addNode: http://example.com/reasoning-demo#hasFriend
✓ addNode: http://example.com/reasoning-demo#manages
✓ addNode: http://example.com/reasoning-demo#isManagedBy
✓ addNode: http://example.com/reasoning-demo#isColleagueOf
✓ addNode: http://example.com/reasoning-demo#hasSupervisor
Canvas: 10 nodes, 0 links
You: Great. Now connect everything — subclass chain, property axioms, domain and range.
Assistant: All nodes exist on canvas — batching all addLink calls, then layout:
22 tool calls ✓
{"jsonrpc":"2.0","id":13,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#Employee","predicateIri":"http://www.w3.org/2000/01/rdf-schema#subClassOf","objectIri":"http://example.com/reasoning-demo#Person"}}}
{"jsonrpc":"2.0","id":14,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#Manager","predicateIri":"http://www.w3.org/2000/01/rdf-schema#subClassOf","objectIri":"http://example.com/reasoning-demo#Employee"}}}
{"jsonrpc":"2.0","id":15,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#Executive","predicateIri":"http://www.w3.org/2000/01/rdf-schema#subClassOf","objectIri":"http://example.com/reasoning-demo#Manager"}}}
{"jsonrpc":"2.0","id":16,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#hasFriend","predicateIri":"http://www.w3.org/2000/01/rdf-schema#subPropertyOf","objectIri":"http://example.com/reasoning-demo#knows"}}}
{"jsonrpc":"2.0","id":17,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#isManagedBy","predicateIri":"http://www.w3.org/2002/07/owl#inverseOf","objectIri":"http://example.com/reasoning-demo#manages"}}}
{"jsonrpc":"2.0","id":18,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#isColleagueOf","predicateIri":"http://www.w3.org/1999/02/22-rdf-syntax-ns#type","objectIri":"http://www.w3.org/2002/07/owl#SymmetricProperty"}}}
{"jsonrpc":"2.0","id":19,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#hasSupervisor","predicateIri":"http://www.w3.org/1999/02/22-rdf-syntax-ns#type","objectIri":"http://www.w3.org/2002/07/owl#TransitiveProperty"}}}
{"jsonrpc":"2.0","id":21,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#knows","predicateIri":"http://www.w3.org/2000/01/rdf-schema#domain","objectIri":"http://example.com/reasoning-demo#Person"}}}
{"jsonrpc":"2.0","id":22,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#knows","predicateIri":"http://www.w3.org/2000/01/rdf-schema#range","objectIri":"http://example.com/reasoning-demo#Person"}}}
{"jsonrpc":"2.0","id":23,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#hasFriend","predicateIri":"http://www.w3.org/2000/01/rdf-schema#domain","objectIri":"http://example.com/reasoning-demo#Person"}}}
{"jsonrpc":"2.0","id":24,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#hasFriend","predicateIri":"http://www.w3.org/2000/01/rdf-schema#range","objectIri":"http://example.com/reasoning-demo#Person"}}}
{"jsonrpc":"2.0","id":25,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#manages","predicateIri":"http://www.w3.org/2000/01/rdf-schema#domain","objectIri":"http://example.com/reasoning-demo#Manager"}}}
{"jsonrpc":"2.0","id":26,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#manages","predicateIri":"http://www.w3.org/2000/01/rdf-schema#range","objectIri":"http://example.com/reasoning-demo#Employee"}}}
{"jsonrpc":"2.0","id":27,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#isManagedBy","predicateIri":"http://www.w3.org/2000/01/rdf-schema#domain","objectIri":"http://example.com/reasoning-demo#Employee"}}}
{"jsonrpc":"2.0","id":28,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#isManagedBy","predicateIri":"http://www.w3.org/2000/01/rdf-schema#range","objectIri":"http://example.com/reasoning-demo#Manager"}}}
{"jsonrpc":"2.0","id":29,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#isColleagueOf","predicateIri":"http://www.w3.org/2000/01/rdf-schema#domain","objectIri":"http://example.com/reasoning-demo#Employee"}}}
{"jsonrpc":"2.0","id":30,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#isColleagueOf","predicateIri":"http://www.w3.org/2000/01/rdf-schema#range","objectIri":"http://example.com/reasoning-demo#Employee"}}}
{"jsonrpc":"2.0","id":31,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#hasSupervisor","predicateIri":"http://www.w3.org/2000/01/rdf-schema#domain","objectIri":"http://example.com/reasoning-demo#Employee"}}}
{"jsonrpc":"2.0","id":32,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#hasSupervisor","predicateIri":"http://www.w3.org/2000/01/rdf-schema#range","objectIri":"http://example.com/reasoning-demo#Manager"}}}
{"jsonrpc":"2.0","id":34,"method":"tools/call","params":{"name":"runLayout","arguments":{"algorithm":"elk-layered","spacing":200}}}
{"jsonrpc":"2.0","id":35,"method":"tools/call","params":{"name":"expandNode","arguments":{}}}
{"jsonrpc":"2.0","id":36,"method":"tools/call","params":{"name":"runLayout","arguments":{"algorithm":"elk-layered","spacing":200}}}
[Ontosphere — 22 tools ✓]
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ runLayout: elk-layered
✓ expandNode
✓ runLayout: elk-layered
Canvas: 10 nodes, 17 links
You: Now for the individuals. Alice is an Executive. Bob, Carol, and Dave have no explicit type — I want to see what the reasoner works out from the relationships alone.
Assistant: Switching to ABox view. Only Alice gets a typeIri — the others are untyped
individuals whose types must be entirely inferred from the edges we assert next.
5 tool calls ✓
{"jsonrpc":"2.0","id":37,"method":"tools/call","params":{"name":"setViewMode","arguments":{"mode":"abox"}}}
{"jsonrpc":"2.0","id":38,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#alice","typeIri":"http://example.com/reasoning-demo#Executive","label":"Alice"}}}
{"jsonrpc":"2.0","id":39,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#bob","label":"Bob"}}}
{"jsonrpc":"2.0","id":40,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#carol","label":"Carol"}}}
{"jsonrpc":"2.0","id":41,"method":"tools/call","params":{"name":"addNode","arguments":{"iri":"http://example.com/reasoning-demo#dave","label":"Dave"}}}
[Ontosphere — 5 tools ✓]
✓ setViewMode
✓ addNode: http://example.com/reasoning-demo#alice
✓ addNode: http://example.com/reasoning-demo#bob
✓ addNode: http://example.com/reasoning-demo#carol
✓ addNode: http://example.com/reasoning-demo#dave
Canvas: 4 nodes, 0 links
You: Now the relationships: Alice manages Carol, Dave manages Bob, Alice is friends with Bob, Bob and Carol are colleagues, and the supervisor chain is Carol → Bob → Alice.
Assistant: Six edges, all nodes already on canvas — batching them all, then layout so you can see the ABox shape before we run the reasoner:
9 tool calls ✓
{"jsonrpc":"2.0","id":43,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#alice","predicateIri":"http://example.com/reasoning-demo#manages","objectIri":"http://example.com/reasoning-demo#carol"}}}
{"jsonrpc":"2.0","id":44,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#dave","predicateIri":"http://example.com/reasoning-demo#manages","objectIri":"http://example.com/reasoning-demo#bob"}}}
{"jsonrpc":"2.0","id":45,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#alice","predicateIri":"http://example.com/reasoning-demo#hasFriend","objectIri":"http://example.com/reasoning-demo#bob"}}}
{"jsonrpc":"2.0","id":46,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#bob","predicateIri":"http://example.com/reasoning-demo#isColleagueOf","objectIri":"http://example.com/reasoning-demo#carol"}}}
{"jsonrpc":"2.0","id":47,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#carol","predicateIri":"http://example.com/reasoning-demo#hasSupervisor","objectIri":"http://example.com/reasoning-demo#bob"}}}
{"jsonrpc":"2.0","id":48,"method":"tools/call","params":{"name":"addTriple","arguments":{"subjectIri":"http://example.com/reasoning-demo#bob","predicateIri":"http://example.com/reasoning-demo#hasSupervisor","objectIri":"http://example.com/reasoning-demo#alice"}}}
{"jsonrpc":"2.0","id":49,"method":"tools/call","params":{"name":"runLayout","arguments":{"algorithm":"dagre-lr","spacing":200}}}
{"jsonrpc":"2.0","id":50,"method":"tools/call","params":{"name":"expandNode","arguments":{}}}
{"jsonrpc":"2.0","id":51,"method":"tools/call","params":{"name":"runLayout","arguments":{"algorithm":"dagre-lr","spacing":200}}}
[Ontosphere — 9 tools ✓]
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ addTriple
✓ runLayout: dagre-lr
✓ expandNode
✓ runLayout: dagre-lr
Canvas: 4 nodes, 6 links
You: Okay, run the reasoner and show me what it inferred.
Assistant: Running reasoning, then layout to surface the inferred edges. Expected:
- Dave gets Manager (domain of manages), then Employee and Person via subclass chain
- Carol and Bob get Employee (range of manages / domain of hasSupervisor), then Person
- Alice gets Manager, Employee, Person via subclass chain from Executive
- isColleagueOf symmetry fires: Carol gets the inverse edge back to Bob
- hasSupervisor transitivity: Carol gets inferred hasSupervisor Alice
- isManagedBy inverse fires: Carol gets isManagedBy Alice, Bob gets isManagedBy Dave
- hasFriend subPropertyOf knows: Alice gets knows Bob inferred
3 tool calls ✓
{"jsonrpc":"2.0","id":52,"method":"tools/call","params":{"name":"runReasoning","arguments":{}}}
{"jsonrpc":"2.0","id":53,"method":"tools/call","params":{"name":"expandNode","arguments":{}}}
{"jsonrpc":"2.0","id":54,"method":"tools/call","params":{"name":"runLayout","arguments":{"algorithm":"dagre-lr","spacing":200}}}
[Ontosphere — 3 tools ✓]
✓ runReasoning: 10707 triples inferred
✓ expandNode
✓ runLayout: dagre-lr
Canvas: 4 nodes, 11 links
You: Dave had no explicit type — what did the reasoner give him?
Assistant: Panning to Dave and expanding his annotation card to show inferred types:
2 tool calls ✓
{"jsonrpc":"2.0","id":55,"method":"tools/call","params":{"name":"focusNode","arguments":{"iri":"http://example.com/reasoning-demo#dave"}}}
{"jsonrpc":"2.0","id":56,"method":"tools/call","params":{"name":"expandNode","arguments":{"iri":"http://example.com/reasoning-demo#dave","expand":true}}}
[Ontosphere — 2 tools ✓]
✓ focusNode
✓ expandNode
Canvas: 4 nodes, 11 links
You: Perfect. Export the complete graph as Turtle.
Assistant: Exporting the asserted graph. Inferred triples live in urn:vg:inferred and are
not included here.
1 tool call ✓
{"jsonrpc":"2.0","id":57,"method":"tools/call","params":{"name":"exportGraph","arguments":{"format":"turtle"}}}
[Ontosphere — 1 tool ✓]
✓ exportGraph: 5291 chars
Canvas: 4 nodes, 11 links
```turtle
@prefix dc: <http://purl.org/dc/elements/1.1/>.
@prefix grddl: <http://www.w3.org/2003/g/data-view#>.
@prefix owl: <http://www.w3.org/2002/07/owl#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix xml: <http://www.w3.org/XML/1998/namespace>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix : <http://purl.org/net/p-plan#>.
@prefix spw: <https://thhanke.github.io/PyodideSemanticWorkflow#>.
@prefix dcterms: <http://purl.org/dc/terms/>.
@prefix p-plan: <http://purl.org/net/p-plan#>.
@prefix prov: <http://www.w3.org/ns/prov#>.
@prefix terms: <http://purl.org/dc/terms/>.
@prefix vann: <http://purl.org/vocab/vann/>.
@prefix dtype: <http://www.linkedmodel.org/schema/dtype#>.
@prefix qudt: <http://qudt.org/schema/qudt/>.
@prefix qudt.type: <http://qudt.org/vocab/type/>.
@prefix skos: <http://www.w3.org/2004/02/skos/core#>.
@prefix vaem: <http://www.linkedmodel.org/schema/vaem#>.
@prefix voag: <http://voag.linkedmodel.org/schema/voag#>.
<http://example.com/reasoning-demo#Person> a owl:Class;
rdfs:label "Person".
<http://example.com/reasoning-demo#Employee> rdfs:subClassOf <http://example.com/reasoning-demo#Person>;
a owl:Class;
rdfs:label "Employee".
<http://example.com/reasoning-demo#Manager> rdfs:subClassOf <http://example.com/reasoning-demo#Employee>;
a owl:Class;
rdfs:label "Manager".
<http://example.com/reasoning-demo#Executive> rdfs:subClassOf <http://example.com/reasoning-demo#Manager>;
a owl:Class;
rdfs:label "Executive".
<http://example.com/reasoning-demo#knows> rdfs:domain <http://example.com/reasoning-demo#Person>;
rdfs:range <http://example.com/reasoning-demo#Person>;
a owl:ObjectProperty;
rdfs:label "knows".
<http://example.com/reasoning-demo#hasFriend> rdfs:domain <http://example.com/reasoning-demo#Person>;
rdfs:range <http://example.com/reasoning-demo#Person>;
rdfs:subPropertyOf <http://example.com/reasoning-demo#knows>;
a owl:ObjectProperty;
rdfs:label "hasFriend".
<http://example.com/reasoning-demo#manages> rdfs:domain <http://example.com/reasoning-demo#Manager>;
rdfs:range <http://example.com/reasoning-demo#Employee>;
a owl:ObjectProperty;
rdfs:label "manages".
<http://example.com/reasoning-demo#isManagedBy> rdfs:domain <http://example.com/reasoning-demo#Employee>;
rdfs:range <http://example.com/reasoning-demo#Manager>;
owl:inverseOf <http://example.com/reasoning-demo#manages>;
a owl:ObjectProperty;
rdfs:label "isManagedBy".
<http://example.com/reasoning-demo#isColleagueOf> rdfs:domain <http://example.com/reasoning-demo#Employee>;
rdfs:range <http://example.com/reasoning-demo#Employee>;
a owl:ObjectProperty, owl:SymmetricProperty;
rdfs:label "isColleagueOf".
<http://example.com/reasoning-demo#hasSupervisor> rdfs:domain <http://example.com/reasoning-demo#Employee>;
rdfs:range <http://example.com/reasoning-demo#Manager>;
a owl:ObjectProperty, owl:TransitiveProperty;
rdfs:label "hasSupervisor".
<http://example.com/reasoning-demo#alice> a <http://example.com/reasoning-demo#Executive>;
rdfs:label "Alice";
<http://example.com/reasoning-demo#hasFriend> <http://example.com/reasoning-demo#bob>;
<http://example.com/reasoning-demo#manages> <http://example.com/reasoning-demo#carol>.
<http://example.com/reasoning-demo#bob> rdfs:label "Bob";
<http://example.com/reasoning-demo#isColleagueOf> <http://example.com/reasoning-demo#carol>;
<http://example.com/reasoning-demo#hasSupervisor> <http://example.com/reasoning-demo#alice>.
<http://example.com/reasoning-demo#carol> rdfs:label "Carol";
<http://example.com/reasoning-demo#hasSupervisor> <http://example.com/reasoning-demo#bob>.
<http://example.com/reasoning-demo#dave> rdfs:label "Dave";
<http://example.com/reasoning-demo#manages> <http://example.com/reasoning-demo#bob>.
<http://example.com/reasoning-demo#Manager> rdfs:subClassOf <http://example.com/reasoning-demo#Person>.
<http://example.com/reasoning-demo#Executive> rdfs:subClassOf <http://example.com/reasoning-demo#Person>, <http://example.com/reasoning-demo#Employee>.
<http://example.com/reasoning-demo#alice> a <http://example.com/reasoning-demo#Person>, <http://example.com/reasoning-demo#Employee>, <http://example.com/reasoning-demo#Manager>;
<http://example.com/reasoning-demo#knows> <http://example.com/reasoning-demo#bob>.
<http://example.com/reasoning-demo#bob> a <http://example.com/reasoning-demo#Person>, <http://example.com/reasoning-demo#Employee>, <http://example.com/reasoning-demo#Manager>;
<http://example.com/reasoning-demo#isManagedBy> <http://example.com/reasoning-demo#dave>.
<http://example.com/reasoning-demo#carol> a <http://example.com/reasoning-demo#Person>, <http://example.com/reasoning-demo#Employee>;
<http://example.com/reasoning-demo#isManagedBy> <http://example.com/reasoning-demo#alice>;
<http://example.com/reasoning-demo#isColleagueOf> <http://example.com/reasoning-demo#bob>;
<http://example.com/reasoning-demo#hasSupervisor> <http://example.com/reasoning-demo#alice>.
<http://example.com/reasoning-demo#dave> a <http://example.com/reasoning-demo#Person>, <http://example.com/reasoning-demo#Employee>, <http://example.com/reasoning-demo#Manager>.
Open this graph in Ontosphere ↗
</details>