# Ontoloom

> MCP server for building and exploring OWL 2 ontologies with AI agents.

- **Type:** MCP server
- **Install:** `agentstack add mcp-extensityai-ontoloom`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ExtensityAI](https://agentstack.voostack.com/s/extensityai)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** BSD-3-Clause
- **Upstream author:** [ExtensityAI](https://github.com/ExtensityAI)
- **Source:** https://github.com/ExtensityAI/ontoloom

## Install

```sh
agentstack add mcp-extensityai-ontoloom
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# ontoloom

MCP tools for building and exploring OWL 2 ontologies with AI agents.

[](https://www.python.org/downloads/)
[](LICENSE)
[]()

ontoloom is an [MCP](https://modelcontextprotocol.io/) server for working with OWL 2 EL ontologies. Each ontology is a single SQLite file. Axioms are typed and validated at the API boundary, and identity is a content hash so duplicates can't slip in.

## Example

A coding agent sketches a tiny solar-system ontology. Create the database, declare a prefix, and add the planet hierarchy:

```
>>> create_ontology(path="solar.ontology.db")

Created ontology at `solar.ontology.db`.

>>> set_prefix(
...     path="solar.ontology.db",
...     name="sol",
...     iri="http://example.org/solar-system#",
... )

Set prefix `sol:` -> `http://example.org/solar-system#`

>>> add_axioms(path="solar.ontology.db", axioms=[...])

Added 6 axioms, skipped 0 axioms.
[bb5496d24bd1] SubClassOf(sol:Star, sol:CelestialBody)
[f3b454b634a3] SubClassOf(sol:Planet, sol:CelestialBody)
[e4e965a69712] SubClassOf(sol:Moon, sol:CelestialBody)
[3f335b35490c] SubClassOf(sol:TerrestrialPlanet, sol:Planet)
[7bc195f4d6a6] SubClassOf(sol:Planet, ObjectSomeValuesFrom(sol:orbits, sol:Star))
[f3de1afbfd6c] SubClassOf(sol:Moon, ObjectSomeValuesFrom(sol:orbits, sol:Planet))
```

Now query the structure. `match_axioms` does structural pattern matching: `?vars` bind to whatever fills the slot, and every match is saved as a selection.

```
>>> match_axioms(
...     path="solar.ontology.db",
...     pattern={
...         "sub_class": "?body",
...         "super_class": {"property": "sol:orbits", "filler": "?center"},
...     },
...     into="orbits",
... )

Saved 2 axioms to "orbits".
[7bc195f4d6a6] SubClassOf(sol:Planet, ObjectSomeValuesFrom(sol:orbits, sol:Star))
[f3de1afbfd6c] SubClassOf(sol:Moon, ObjectSomeValuesFrom(sol:orbits, sol:Planet))
```

Selections persist and compose. A second match grabs every axiom where `sol:Planet` is the sub-class; `create_selection` intersects the two to find the one axiom that is *both* about Planet *and* describes an orbit.

```
>>> match_axioms(
...     path="solar.ontology.db",
...     pattern={"sub_class": "sol:Planet", "super_class": "?super"},
...     into="planet_facts",
... )

Saved 2 axioms to "planet_facts".
[7bc195f4d6a6] SubClassOf(sol:Planet, ObjectSomeValuesFrom(sol:orbits, sol:Star))
[f3b454b634a3] SubClassOf(sol:Planet, sol:CelestialBody)

>>> create_selection(
...     path="solar.ontology.db",
...     name="planet_orbit",
...     expr={"intersect": ["orbits", "planet_facts"]},
... )

Saved 1 axiom to "planet_orbit".
[7bc195f4d6a6] SubClassOf(sol:Planet, ObjectSomeValuesFrom(sol:orbits, sol:Star))
```

## What you can do

- Build an ontology from scratch by talking to an agent
- Poke around an existing one: search by text or structure, inspect entities
- Hand an agent an existing ontology and ask it to clean up or extend
- Dump everything to JSONL for sharing or archival
- Manage prefix mappings and axiom-level annotations

## Tools

**Setup**
`create_ontology` | `set_prefix` | `remove_prefix`

**Build**

- `add_axioms` - add validated axioms; duplicates are skipped
- `remove_axioms` - remove by hash or by axiom selection
- `annotate_axiom` - change axiom-level annotations without touching identity
- `replace_axiom` - atomic delete + add for one axiom
- `rename_iri` - rewrite an IRI across all (or scoped) axioms

**Query**

- `describe_ontology` - entity and axiom counts, top entities, prefix mappings
- `get_entity` - roles, annotations, and asserted axiom counts for one entity
- `find_entities` - text search, optionally filtered by role or namespace
- `find_axioms` - text search on axiom-level annotations
- `find_duplicate_entities` - entities sharing the same value for an annotation property
- `match_axioms` - structural pattern matching with `?vars` and `*` wildcards

**Selections** - named, persistent sets of axiom hashes or entity IRIs

- `create_selection` - build from set algebra over existing selections
- `read_selection` - paginated view with present/missing visibility
- `list_selections` - show all named selections
- `remove_selections` - drop one or more selections

**Export**
`export_jsonl` - dump all axioms to a sorted JSONL file

## Getting started

Requires Python 3.12 and [uv](https://docs.astral.sh/uv/).

```bash
git clone git@github.com:ExtensityAI/ontoloom.git
cd ontoloom
```

### Claude Code plugin (recommended)

```
/plugins add /path/to/ontoloom/plugins/claude-plugin
```

### Manual MCP configuration

Drop this into your `.mcp.json`, adjusting the paths for your clone:

```json
{
  "mcpServers": {
    "ontoloom": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--project", "packages/mcp", "python", "-m", "ontoloom_mcp.server"]
    }
  }
}
```

### Standalone

```bash
uv run --project packages/mcp python -m ontoloom_mcp.server
```

### Sandboxing (optional)

Set `ONTOLOOM_WORKSPACE_ROOT=/path/to/workspace` to confine all `Ontology(...)`, `export_jsonl`, and import paths to that directory tree. Useful when running an agent that may take instructions from untrusted documents - the agent can't open or write SQLite files outside the workspace. Unset (default) means unrestricted single-user behavior.

## How it works

Each ontology lives in a single `.db` file that works the same whether it has a dozen axioms or millions. SQLite is the source of truth; the MCP layer is the only writer, so axioms are always validated before they reach disk.

Axioms are typed Pydantic models hashed by canonical logical content, ignoring annotations - you can edit a comment without changing the hash, and exact duplicates are caught automatically.

## Status

Alpha. The pieces work and are in use, but the API isn't frozen yet. Issues and PRs welcome.

## License

BSD-3-Clause - see [LICENSE](LICENSE).

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ExtensityAI](https://github.com/ExtensityAI)
- **Source:** [ExtensityAI/ontoloom](https://github.com/ExtensityAI/ontoloom)
- **License:** BSD-3-Clause

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-extensityai-ontoloom
- Seller: https://agentstack.voostack.com/s/extensityai
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
