Cortex
An ontology-backed knowledge graph memory store with branch-based ingestion, provenance, inference, and full-text search — exposed to AI agents over MCP.
📖 Documentation — , a , the , the , the , and .
Power your agent
การติดตั้งจากผู้เผยแพร่ ไม่ใช่เอนด์พอยต์ของ PlugMCP
URL แบบรีโมตหรือคำสั่งบนเครื่องของคุณ? การติดตั้งสองแบบต่างกันอย่างไร
รันบน PlugMCP
A new server you create. It is not this listing's official endpoint. Use the publisher install when you want their URL and their credentials.
เปิดจากผู้เผยแพร่
An ontology-backed knowledge graph memory store with branch-based ingestion, provenance, inference, and full-text search — exposed to AI agents over MCP.
📖 Documentation — , a , the , the , the , and .
An MCP server to build knowledge graph of OWL ontologies
Adding the starter auto-configures a complete knowledge graph memory for your Spring Boot application:
Cortex bean — the entry point to the knowledge graph, backed by Apache Jena. The approved assertions always live in a TDB2 store — in memory by default, or on disk with cortex.persistent=true. The inference closure and the full-text index built over it are derived data: an in-memory cache, rebuilt from the assertions on every startup, regardless of cortex.persistent.ontology.ttl), the SHACL shapes ingested data must conform to (ontology.shapes), and inference rules (ontology.rules) on the classpath. The cortex.ontologies, cortex.shapes, and cortex.rules properties each accept a list of resources, merged in order, so a graph can be built from several ontology, shape, and rule files.rdf:type, rdfs:label, and rdfs:comment allowed beyond it. Linting returns the validated Turtle, ready to ingest, and ingestion fails fast on anything that does not lint clean.prov:Activity (started when the branch is staged, ended when it is approved), and every approved statement is reified and linked to its activity with prov:wasGeneratedBy.rdfs:label and rdfs:comment, held as separate fields so a name outranks a description. rdf:type is deliberately not indexed: class URIs would mix their tokens into the same relevance space as human-readable prose, giving every typed resource the same filler terms./export, and a Turtle document can be uploaded at /import, which stages it on a branch for review like any other ingest rather than replacing the graph.Add the Spring Boot starter to your project.
Gradle
implementation("ai.chatur:cortex-spring-boot-starter:0.1.4")
Maven
<dependency>
<groupId>ai.chatur</groupId>
<artifactId>cortex-spring-boot-starter</artifactId>
<version>0.1.4</version>
</dependency>
All properties are bound under the cortex prefix. ontologies, shapes, and rules each accept a list of classpath:/file: resources, merged in order.
cortex.s3.proxyis the whole story. The AWS SDK resolves proxy settings from JVM system properties and environment variables by default, so leavingcortex.s3.proxyunset would not mean "no proxy" — it would mean "whatever proxy the deployment environment happens to name", with backup uploads silently routed through it. Cortex therefore defaults both discovery settings tofalse: an unset proxy is genuinely no proxy. If you want the SDK's ambient discovery — a corporate network that setsHTTPS_PROXYglobally, say — set the corresponding property totrue.
Single-JVM constraint: when
cortex.persistent=true, the TDB2 store is opened withTDB2Factory.connectDataset, which does not support two JVMs concurrently opening the same directory. Run one instance per persistent store directory.
A Quartz job can periodically snapshot the whole assertions dataset — the approved assertions, every staged branch, and the provenance graph — and upload it to S3. The snapshot is TDB2's own DatabaseMgr.backup: gzipped N-Quads, taken inside a read transaction, so it is a consistent snapshot that does not lock out concurrent ingestion or approval.
This is the real backup mechanism. /export is not — it carries only the approved assertions, for reading and sharing.
Backups are off by default, so the starter does not bring the dependencies they need. To switch them on, add:
implementation(platform("software.amazon.awssdk:bom:2.46.7"))
implementation("software.amazon.awssdk:s3")
implementation("software.amazon.awssdk:apache-client")
implementation("org.springframework.boot:spring-boot-starter-quartz")
apache-client is not optional: the s3 artifact declares the synchronous HTTP clients at test scope and ships only the asynchronous Netty one, so without it the synchronous S3Client fails to build. It is also what backs cortex.s3.proxy.
Then configure it — this example targets a local MinIO with no authentication:
cortex:
persistent: true
backup:
enabled: true
interval: 6h
s3:
enabled: true
endpoint: http://localhost:9000
bucket: cortex-backups
region: us-east-1
auth: anonymous
path-style-access: true
Backups require
cortex.persistent=true. A TDB2 backup is an admin operation on an on-disk store; the in-memory store used by default has no location to write a backup beside. Enabling backups without persistence fails at startup rather than booting an application that reports healthy and never backs anything up. The same is true of a missing bucket, missing static credentials, a non-positive interval, and the dependencies above.
Backups are scheduled, so a restart discards every approval made since the last one — up to a full cortex.backup.interval, 24 hours by default. Cortex therefore takes one final backup as the context closes and blocks shutdown until it has uploaded. It is on by default whenever backups are enabled; set cortex.backup.onShutdown=false to turn it off without giving up scheduled backups.
The final backup runs after the web server has stopped accepting requests and after the scheduler has quiesced, so it snapshots a store nothing is still writing to — including waiting out a scheduled backup that happens to be in flight. It is an ordinary backup under the same key prefix, so a restore picks it up as the most recent object with no extra configuration.
The wait is deliberately unbounded. A large store on a slow link takes as long as it takes, and a bounded wait would kill the upload partway through on exactly the stores that most need it. A backup that fails — bad credentials, a missing bucket — is logged and shutdown continues, so a misconfigured bucket can never make the application impossible to restart; only a genuinely slow upload holds shutdown open. If your orchestrator sends
SIGKILLafter a grace period, size that grace period against how long a backup of your store actually takes.
Backup files accumulate under <cortex.assertionsLocation>/Backups/ and are never deleted: the upload is a copy, not a move, so a bucket misconfiguration can never destroy data. Pruning them is left to whatever manages that volume — or to an S3 lifecycle rule for the uploaded copies.
The inverse of a backup: on boot, Cortex can download the most recent backup from S3 and load it into the assertions store before the application serves traffic, so an instance whose local disk was replaced comes up with its data. The inference closure and full-text index are then rebuilt from the restored assertions on startup as usual, with no extra step.
This treats S3 as the source of truth and the local store as replaceable: the restore is a wipe-and-load that runs on every boot — it clears the store and loads the latest backup over it, restoring the approved assertions, every staged branch, and the provenance graph at full fidelity. It needs the same dependencies as backups (spring-boot-starter-quartz is not among them — restore uses no scheduler, but software.amazon.awssdk:s3 and apache-client are required), plus an enabled S3 client:
cortex:
persistent: true
restore:
enabled: true
s3:
enabled: true
endpoint: http://localhost:9000
bucket: cortex-backups
region: us-east-1
auth: anonymous
path-style-access: true
The switch is independent of cortex.backup.enabled: an instance may restore from another's uploads without scheduling backups of its own, or the same instance may do both. When it does both and cortex.backup.keyPrefix is customized, set cortex.restore.keyPrefix to match so the restore looks under the same prefix the backups were written to.
Restore requires
cortex.persistent=true, an enabled and configured S3 client, and the AWS SDK dependencies — each checked at startup, so a half-configured restore fails the context rather than silently booting an empty graph the operator expected to be seeded. The one case that is not an error is an empty bucket: a first-ever deployment with no backup yet logs and starts empty.
A restore is destructive by design — it discards the local store's current contents. That is the intended behavior when S3 is your source of truth (an ephemeral volume, a fresh replica), but it means any local writes not yet captured by a backup are lost on the next boot. If that is not what you want, leave
cortex.restore.enabled=false.
Cortex is split across five Gradle modules; the first four are published independently to Maven Central.
The starter registers an MCP server (via Spring AI) through which agents interact with the knowledge graph.
The repository also ships cortex-schema (cortex-schema-plugin/), a Claude Code plugin that authors the three schema files a Cortex application needs — ontology.ttl, ontology.shapes, and ontology.rules — from a plain-English description of your classes, relations, and rules.
Its /generate-cortex-resources skill gathers requirements interactively, then generates a mutually-consistent set of files: an OWL 2 DL ontology, closed-world SHACL shapes that reject anything the ontology doesn't recognize (including direct assertion of inferred-only classes), and Jena reasoner rules for controlled inference — cross-checked for consistency before being written to your application's src/main/resources/. The namespaces are yours to choose; see the plugin README for the one namespace Cortex itself reserves.
To use it, add the plugin directory as a marketplace in Claude Code and install the plugin:
/plugin marketplace add ./cortex-schema-plugin
/plugin install cortex-schema@cortex-schema
Then invoke /generate-cortex-resources and describe your ontology. See the plugin README for the full workflow and an example.
The starter also serves a small UI for exploring the graph and reviewing what agents have staged. The navbar carries a search bar — press Enter to search, no button needed.
rdfs:label and rdfs:comment, with a name-over-description boost) to a single field fed by rdfs:label, rdfs:comment, and the SKOS labelling and note properties (skos:prefLabel, skos:altLabel, skos:definition, skos:note, …), analysed with Lucene's EnglishAnalyzer. Matching is now exact after analysis — recall comes from English stemming rather than edit-distance fuzz — so a typo that used to squeak through no longer does, while plurals and word forms still match. Ranking is Lucene relevance weighted by how often a resource is opened; the name-over-description boost is gone. There is no API change.CortexStats.inferenceTriples() renamed to inferredTriples(), and it now counts only derivations. It used to be the size of the whole inference dataset — the approved assertions and the ontology's own axioms included — while the home page labelled it "Inferred triples". It now reports that dataset less the assertions and less the ontology axioms, so it answers "what did the reasoner add?". Expect a smaller number than 0.1.3 reported for the same graph. assertionTriples() is unchanged.ProvenancedStatement gained an origin component. describe used to report every statement without provenance as inferred, which mislabelled the ontology's own axioms: the reasoner is bound to the ontology as its schema, so axioms such as rdfs:domain are materialized alongside the reasoner's conclusions and carry no provenance either. The new StatementOrigin (ASSERTED, ONTOLOGY, INFERRED) tells the three apart, and /describe badges them accordingly. This is source-breaking for code constructing a ProvenancedStatement — the canonical constructor now takes a fourth argument. Reading created() is unaffected: it is still non-null exactly when the origin is ASSERTED.0.1.1 changes what /export and /import mean. Cortex is pre-1.0, so the following were changed rather than deprecated:
CortexArchive.importAssertions(String) removed. /import no longer restores a dataset — it stages the upload for review through ingest. The destructive whole-dataset restore is gone with it, and the replacement for it is the scheduled backup, which captures strictly more (staged branches and provenance, not just approved assertions). To restore one, enable restore on startup, or stop the application and load the .nq.gz into the store with Jena's tdb2.tdbloader.CortexArchive.getAssertions() removed. It served the approved assertions as TriG and had no caller; exportAssertions() now returns exactly that, as Turtle.CortexArchive.exportAssertions() returns Turtle, not TriG, and only the approved assertions. It previously serialized the entire dataset — every staged branch and the provenance graph included. /export accordingly serves cortex-assertions-<date>.ttl as text/turtle rather than .trig as application/trig./import accepts .ttl only, and no longer replaces the graph. An uploaded document is linted, SHACL-validated, reduced to what is novel, and staged on a branch; the browser lands on /branches. A .trig upload is rejected with an explanation. Anything automating the old restore behaviour must change: an import can now be rejected by a reviewer, and never overwrites what is already approved./branches, not /assertions. Update any UI automation following that redirect.0.1.0 is a breaking release. Cortex is pre-1.0, so the following were changed rather than deprecated:
throws IOException removed from the entire Cortex API. Every occurrence was a phantom, traced to serializing into an in-memory StringWriter/ByteArrayOutputStream whose close() cannot fail but still declares the checked exception. Cortex, JenaCortex, and every method across all nine role interfaces no longer declare it. This is source-breaking: a catch (IOException) around a call that can no longer throw one is now a compile error, since IOException is a checked exception the try block no longer produces. Remove the catch (or the throws clause of your own method, if it only existed to relay Cortex's).Cortex split into nine role interfaces: CortexOntology, CortexLinter, CortexIngestor, CortexBranches, CortexArchive, CortexQuery, CortexSearch, CortexStatistics, and CortexInference. Cortex still extends all nine, so existing code that depends on Cortex keeps compiling and the single Cortex bean still satisfies every role by type — this is not source-breaking. New and existing consumers are encouraged to narrow their constructor parameter to the role they actually use (e.g. a search controller takes CortexSearch, not Cortex), which is also what makes them trivially fakeable in tests without stubbing the whole surface.Term encoding changed for unprefixed IRIs. For a URI with no matching namespace prefix, Term.localName() is now the full URI — matching Term's own documented contract — instead of the bare local name after the last #//. This is user-visible wherever unprefixed resources are rendered: /assertions?type=, /describe?uri=, /search link text, and searchSubjects/describe results returned to MCP agents. Prefixed IRIs (the common case, if your ontology declares prefixes for its namespaces) are unaffected.cortex.indexLocation removed. The full-text index is now always an in-memory Lucene index (ByteBuffersDirectory), regardless of cortex.persistent, since it is derived data rebuilt from the assertions on every startup. If you set this property, remove it — it is silently ignored.OntologyClass's term component renamed to type. Update any code constructing or destructuring OntologyClass positionally or by component name./assertions/{id} route was removed; use /describe?uri={uri} instead (see Web UI).CortexBranches#reject) and route (POST /branches/{branch}/reject) were already named reject; only the web UI button previously read "Delete" and has been relabeled "Reject" to match. No API or route change, but update any UI automation asserting on the old button text.An MCP server to build knowledge graph of OWL ontologies
เครื่องมือ
ยังไม่มีรายการเครื่องมือ เซิร์ฟเวอร์แบบรีโมตจะได้รายการหลังการตรวจสอบสถานะครั้งแรก
FAQ
คัดลอกคอนฟิก stdio สำหรับ Cursor, Claude Desktop, Claude Code หรือ VS Code ได้ในหน้านี้ คอนฟิกนี้ใช้การติดตั้งของผู้เผยแพร่ ไม่ใช่พร็อกซีของ PlugMCP
ระเบียนนี้ไม่ได้ระบุตัวแปรสภาพแวดล้อมที่จำเป็น
Cortex ทำงานแบบโลคัลผ่าน stdio
ตรวจสอบล่าสุดเมื่อ 2026-10-27 An MCP server to build knowledge graph of OWL ontologies