MESSAI collab · ontology workstream · ISMET community · draft 9 Oct 2026
From our parameter vocabulary to a community ontology
MESSAI already runs on a controlled vocabulary: every extracted value keeps its raw name and unit, about half are mapped to a canonical parameter (45 % in the snapshot manifest of 7 Jul 2026), and a mapped parameter may have a node in a graph whose edges are mostly literature-inferred. Nobody outside MESSAI has been asked whether it is right, nobody can cite a version of it, and an AI assistant connected to our MCP server cannot ask it a question. This page sets out what is in place, what is missing, and the work that would make it something the field adopts, recognises, checks and helps write.
The question for the community
“What would have to be true of this vocabulary for your group to report its own results in it, and to correct it when it is wrong?”
The answers decide the order of the to-dos below. A vocabulary that only we maintain is not yet a community standard; it becomes one when other people depend on it and can change it. Whether it is an ontology depends on its definitions, relations and identifiers, not on who uses it.
How a value gets its name
The path one number takes from a paper to an AI assistant, and how much of each step exists. Nothing here is new: it is the pipeline described in the audit, put in order. A step marked “Proposed, not built” does not exist yet.
A paper reports a value in its own words
In placeExtraction keeps what the paper said: its name for the quantity, its unit and the sentence the value came from. The raw name is kept; a first slug from the alias file is attached beside it, not in its place.
Browse the extracted valuesThe name is matched to one parameter
Partly in placeThe raw name goes through fixed rules in order: an exact match against the alias index, then a fuzzy match for names of several words; names still unmatched go through a few rules that depend on the unit. A single word with no exact match is refused, not guessed. A name that matches nothing gets no slug. An AI classifier may propose aliases; only deterministic code writes slugs to the database: the extractor’s alias lookup and the backfill. The TypeScript and Python matchers do not yet agree on every name.
See the five layersThe parameter gets a definition and a kind
Partly in placeA definition gives the category, the unit and a plausible range. The kind says which physical quantity the slug measures, so values in different units can be converted to SI and compared. A slug with no kind is never used for modelling. Some slugs that carry data still have no definition.
See what is missingThe parameter gets a role and a place in the causal graph
Partly in placeThe role says whether a parameter is an outcome, a condition or context, which decides how a model may treat it: in one modelling run of the corpus-screening agent, conditions set by the experimenter and fitted with a population-mean prior did not mix, while outcomes mixed better but were under-sampled. Role can also depend on the study: applied voltage is a condition in an MEC and an outcome in an MFC. Four role vocabularies exist side by side and are not reconciled. A small curated graph links parameters by cause; a larger snapshot feeds the knowledge-graph page.
Open the knowledge graphA release gets a version and a permanent address
Proposed, not builtNot built. There is a package version, but no ontology release with a changelog and a DOI, and a term has no permanent address, so a paper cannot say which vocabulary it reported against. This is the first of our to-dos.
See our to-dosPeople and AI assistants use it, and can correct it
Partly in placeAn MCP client can read a parameter’s category, slug, unit and graph neighbours today. It cannot resolve a lab’s column name, and it sees no kind, role, alias or version. No expert outside MESSAI has reviewed a definition, and there is no process to propose a change.
See the MCP coverage
What exists today
The “ontology” is five stacked vocabularies, not one. They were built for different jobs and have not been reconciled. The counts below are from the staging audit in docs/onboarding/categorization-and-ontology.md (7 September 2026); counts marked 12 Oct 2026 were measured again on that date.
| Layer | Vocabulary | Size | Used for |
|---|---|---|---|
| 1 · Category | ParameterCategory enum plus a free-text subcategory | 18 values, 15 used; 179 subcategories | Browsing, graph colour |
| 2 · Canonical slug | snake_case slugs, some legacy camelCase | 835 definitions; 492 slugs seen in rows, 463 of them with a definition | Everything downstream: priors, predictor, catalogue |
| 3 · Kind | The physical quantity a slug measures | 290 slugs → 41 kinds; 41 SI bases; 240 unit factors (normalize-to-si.py, 26 Oct 2026) | SI normalisation, whether a row can be modelled, prior bucketing |
| 4 · Role | Four competing vocabularies | 25 primary roles · 3 outcome/condition/context classes · 4 causal roles · 5 node classes (an evidence status, not a role) | Causal graph, priors, graph encoding |
| 5 · Graph node | A curated subgraph and a full snapshot | 31 nodes, 29 edges curated; 826 nodes, 2,792 edges in the snapshot | The causal model, the knowledge-graph page |
The package that ships the definitions publicly is @messai-io/mess-parameters (v0.3.0, CC-BY-4.0, with a CITATION.cff). It is the layer meant for outside use, although on 12 Oct 2026 it was not on the public npm registry.
Two names from the shared resolver tests, followed through every layer they reach. The TypeScript and Python resolvers are one mapper since 24 Oct 2026 and return the same slug; until then they split on power density.
- Slug
coulombic_efficiencyBoth resolvers return this slug: an agreed case in the resolver tests.
- Category · definition unit
ELECTROCHEMICAL%The category is a browsing label; it does not decide how a value is used. The definition’s unit is %.
- Kind · SI base
fractionfractionThe kind converts the value to its SI base, so 45 % and 0.45 become the same number.
- Role · run-01 · primaryRole
OUTCOMEnoneAn outcome in the modeller’s three-class vocabulary (run-01, 163 papers). No entry in the 25-value
primaryRolevocabulary. - Curated graph
cod_removalcoulombic_efficiencyenergy_efficiencyh2_yieldspecific_h2_productionOne edge in, from
cod_removal(confidence high, 29 co-observations), three out (confidence medium, no co-observations). All four edges rest on domain knowledge; two values reported together are not evidence that one causes the other.
1,575 distinct facts in 796 papers (2,511 rows). 834 facts are flagged modelable; 813 of them pass the shared modelling-pool filter.
- Slug
power_densityBoth languages return the areal slug, and the unit does not decide it. Until 24 Oct 2026 the Python resolver returned
power_density_volumetrichere. Still a pending test case: should the slug follow the unit, or refuse (Q-O3)? - Category · definition unit
MATERIALSmW/cm²The definition is “Power Density (Basis Unresolved)”, unit mW/cm².
- Kind · SI base
power_densityW/m^2The areal kind converts mW/m² to W/m². A volumetric unit under this slug is routed to the volumetric kind by
route_kind(), never pooled with areal values. - Role · run-01 · primaryRole
OUTCOMEnoneAn outcome in the modeller’s vocabulary. No entry in
primaryRole. - Curated graph
power_densityThe curated graph’s power-density node, renamed from the legacy
powerDensityon 19 Oct 2026.
Rows filed under power_density_volumetric: 463 in W/m³ (112 papers), not flagged modelable; 136 with an areal unit, held out as a basis conflict (50 papers); 44 not converted (20 papers). Both priors fitters also admit the W/m³ rows by their unit.
What is missing
Each item is a fact about the repository today, not an opinion. Together they are why the vocabulary cannot yet be adopted, cited or checked by anyone outside MESSAI.
- Counts disagree. The public package and the /parameters methodology page say 704 parameters in 13 categories; the packaged definitions file is pinned at 825; staging holds 835 definitions (825 active) using 15 of the 18 categories the schema allows, and the package’s own CITATION.cff also says 835. A reader cannot tell which one “the ontology” is.
- No versioned, citable release. There is a package version but no ontology release with a changelog and a DOI, so a paper cannot say which vocabulary it reported against.
- No stable identifiers. A term is a database row and a slug. Nothing resolves a term to a permanent address, and the definition table has no column for an external identifier.
- No mapping to anyone else’s vocabulary. Units, chemicals, organisms and environments each have a community vocabulary. We do not point at any of them, so nothing we publish links to the wider data web.
- Undefined terms carry real data. On staging on 12 Oct 2026, 29 slugs in live extracted rows had no definition, carrying 4,985 rows; the largest are legacy names such as
powerDensity(1,418 rows) andcurrentDensity(715), and one,_provenance_metadata(936), is not a quantity at all. A legacy name is not assumed to be an alias of a canonical term until someone checks its rows. 372 of the 835 definitions had never matched a live row. - A table listed slugs twice. Until 13 Oct 2026,
SLUG_TO_KINDin normalize-to-si.py named 13 slugs twice, and Python kept the second entry. Forpower_density_volumetricthat entry was areal power density, so 136 live rows in 50 papers with an areal unit under the volumetric slug had been converted to W/m² and flagged modelable on staging. The table now has one entry per slug and a test fails on any repeat; those rows are held out as a basis conflict. Whether the slug or the unit is wrong is still undecided (Q-O3). The trace above follows one such value. - Roles are not one thing. Four role vocabularies coexist, and they are independent of each other.
- No outside review. No domain expert outside the project has been asked to check a definition, and agreement between two people labelling the same raw names has never been measured.
- No way to propose a change. There is no documented process for adding, merging or retiring a term, and no named reviewer for any category.
- Not reachable from an AI assistant. The MCP server returns a parameter’s slug, name, unit and category, and its graph neighbours. It cannot map a lab’s own column name to a slug, and it returns none of a term’s kind, role, aliases or version.
Four goals, and what each one asks of us
These are separate. A vocabulary can be adopted without being recognised, and recognised without being right. The to-dos in the next sections are tagged with the goals they serve.
Adopted
Other people use itReporting in it has to cost less than reporting without it. That means a lab can paste its own column names and get slugs back, an assistant can resolve a term in one call, and the minimum-reporting checklist uses the same slugs, so the checklist and the ontology cannot drift apart.
Served by: Reconcile the counts and cut a versioned release · Close the undefined terms and choose one role vocabulary · Build the MCP additions
Recognised
Other people can cite and link itA released version with a DOI, a permanent address for every term, a licence, and mappings to the vocabularies other fields already use. Recognition is mostly plumbing: nobody cites “whatever is on the website today”.
Served by: Reconcile the counts and cut a versioned release · Give every term a permanent address · Map the terms to existing vocabularies · Register and describe it
Validated
Other people have checked itExperts review a sample of definitions per category, two annotators label the same raw names and we report their agreement, and the questions the ontology exists to answer are written as tests that run on every change. Authors verifying their own papers’ extracted parameters is the same check from the other side.
Served by: Close the undefined terms and choose one role vocabulary · Map the terms to existing vocabularies · Validate with people outside the project
Community-informed
Other people can change itA documented route to propose, review and accept a term, a named reviewer per category, a term lifecycle that retires rather than deletes, and a public change log. The parameter wiki already holds edits as pending until a moderator approves them; it could carry term proposals once it accepts terms that have no definition yet.
Served by: Write the contribution and review process · Validate with people outside the project
The ontology in MCP
MESSAI’s MCP server is public, read-only and has 15 tools. It exposes the vocabulary only as a side effect of other queries. An assistant that can resolve a term, read its definition and see which version it is looking at would reuse the ontology without anyone opening a web page.
What a client can reach today
| Layer | Coverage | How it is reached today |
|---|---|---|
| Category | Partial | list_parameters returns it and filters by it. The subcategory is not returned. |
| Canonical slug | Partial | list_parameters searches names and descriptions. A column name that is not a name or description match finds nothing. |
| Aliases (raw name → slug) | None | The alias index (6,678 aliases in 430 groups, 79 more pending review) sits in a file used by the backfill scripts. No route serves it. |
| Kind and SI unit | None | Only the unit string is returned. Distributions are grouped by SI unit, but the kind is not named. |
| Role | None | Not returned by any tool. |
| Graph node | Partial | get_parameter_relationships returns neighbours in the curated graph and literature correlations, with the number of papers. |
| Ontology version | None | No tool says which version of the vocabulary produced its answer. |
What we propose to add
| Addition | Type | What it does | Needs first |
|---|---|---|---|
| resolve_term | Tool | Takes up to 25 raw terms (a column header, a name from a paper) with an optional unit, and returns ranked candidate slugs with the match tier and score. It applies the same refusals as the backfill: a single word with no exact match returns no candidate. Each result links to the term-proposal page for a miss. | A new public route over the alias index. The index lives in files read by Python and TypeScript scripts, so the route either ports the matcher or reads a table the backfill also writes. |
| get_parameter_definition | Tool | Returns one term in full: category and subcategory, kind and SI unit, roles, aliases, plausible range, graph neighbours, the ontology version, and external identifiers once mapped. | The definitions route extended with the fields above. The version and the identifiers depend on the release and alignment to-dos. |
| messai://ontology | Resource | A resource with the version, the layer list and per-layer counts, plus messai://ontology/{slug} per term, so a client can attach the vocabulary to a conversation without a tool call. | The same extended route, and the release to-do for the version string. |
| map_my_columns | Prompt | A prompt that takes a pasted spreadsheet header row, calls resolve_term for each column, reports the unit conversion resolve_term returns without converting anything itself, refuses a conversion when the species, reference electrode or area or volume basis is missing, and reports which columns have no slug and the reporting rules on caution. | Nothing beyond resolve_term. |
How it goes in, following docs/mcp.md
- Wrap only routes that never read the session. Run the grep from the checklist on each new route: it must find no
getServerSession,cookies()orheaders(). A tool must not let a signed-in client write through a “read-only” call. - Keep proposals out of MCP. The server is read-only. A miss returns a link to the term-proposal page on the website; the proposal itself is made there, by a person, and held as pending.
- Shape the output. Return the match tier, the score, the unit conversion that applies and the ontology version with every answer. Stay well under the 60,000-character cap by limiting a batch to 25 terms.
- Set the cost.
resolve_termdoes an index lookup per term, so it takes a cost inMCP_TOOL_COSTSof 1 per call; the shipped tools cost 1 each exceptpredict_performanceat 10 andupdate_with_my_dataat 3. - Test, smoke, document. Add the mock-the-route tests and the registry entry, add the names to
EXPECTED_TOOLSandTOOL_CALLSinmcp-smoke.py, and update the tool lists on/mcpand/api-docsin English and German, and the counts in docs/mcp.md.
Our to-dos
Estimates are our own, in working days for one person, and none is scheduled. Order follows dependency: a release needs the counts reconciled, identifiers need a release, and the MCP version string needs both.
Reconcile the counts and cut a versioned release
~3 daysProposedDecide what “the ontology” contains, regenerate the packaged definitions from staging (the pinned file is 10 behind), and release it with a changelog and a DOI. The 704, 825 and 835 figures then become one number with a version. Release through the changesets flow in docs/releasing.md.
Close the undefined terms and choose one role vocabulary
~2 weeksProposedWrite definitions for the 29 undefined slugs that carry data, review the 341 definitions no row has matched, and pick which of the four role vocabularies is the ontology’s, keeping the others as documented mappings. Promote
canonical_slugout of JSONB into a column, as Rule §8 asks, since 88 code sites filter on it.Give every term a permanent address
~1 weekProposedOne stable URL per term that returns the definition as a page for people and as JSON-LD for machines, and an identifier column on the definitions table. The namespace is an open question: it can sit on messai.io or on something neutral that ISMET could later hold.
Map the terms to existing vocabularies
~2 weeksProposedStart by searching for an existing microbial-electrochemistry ontology; we have not confirmed whether one exists, and the page should say so if none does. Then map where a community vocabulary exists, for example QUDT or UO for units, ChEBI for chemicals, ENVO for environments and NCBI Taxonomy for organisms, and publish the mapping as an SSSOM file with its coverage stated per layer, including what could not be mapped.
Write the contribution and review process
~1 weekProposedA term lifecycle (proposed, reviewed, accepted, deprecated, never deleted), a template for proposing a term, a named reviewer per category, and a public change log. Reuse the parameter wiki’s approval gate rather than build a second one. Add it to the CONTRIBUTING file of the public package.
Validate with people outside the project
~2 weeksProposedTwo annotators label the same 200 raw names without seeing the pipeline’s answer, and we report their agreement and the pipeline’s agreement with each. Experts review a sample of definitions per category. Write the questions the ontology should answer as tests. Add an “is this right?” control to a paper’s extracted parameters for its authors.
Build the MCP additions
~4 daysProposedThe tool, definition route, resource and prompt in the MCP section, following docs/mcp.md. Depends on the alias route and on the release for its version string.
Register and describe it
~1 weekProposedAfter the above: a short data descriptor or preprint on the ontology, and registration in a vocabulary registry such as FAIRsharing. Not before there are outside reviewers to name and a release to point at.
Timeline
Dates marked “roadmap” are in docs/roadmap/2026-09-roadmap.md. Dates marked “proposed” are ours and are not on the roadmap.
- 9 Oct 2026 · roadmap D1-M1ISMET partnership proposal, with the claim-an-ontology-category ask
D1-M1. The ask this page elaborates: ISMET members take stewardship of a category.
- 10 Oct 2026 · roadmap B3-M1Minimum-reporting checklist v1
B3-M1. Written with the ontology’s slugs as its field names, so the two share one vocabulary from the start.
- 15 Oct 2026 · roadmap D1-M2Meeting with ISMET
D1-M2. The ask there is a named liaison and a newsletter or webinar slot; the ontology is one of the things a liaison would route.
- end Oct 2026 · proposedRelease candidate with reconciled counts
The release to-do. One number for the size of the ontology, a changelog, and the undefined terms listed openly if they are not yet closed.
- 14 Nov 2026 · roadmap D3-M2mess-parameters release carrying the checklist schema
D3-M2. The first release a stranger can cite that contains both vocabularies.
- end Nov 2026 · proposedMapping and agreement report
Coverage of the external mapping per layer, and the two-annotator agreement result, whatever it is.
- by 19 Dec 2026 · proposedresolve_term and the definition tool live
Checked by the live MCP smoke script, and listed on /mcp and /api-docs.
- Phase P1 · roadmap D1-M5Papers verified by their authors
D1-M5. The roadmap’s own target is at least 5.
- Phase P2 · roadmap D1-M6Checklist endorsed or co-published with ISMET
D1-M6. The point at which the vocabulary is no longer only ours.
What we ask of partners
- Claim a category. Take stewardship of one of the 15 categories in use: read its definitions, flag the wrong ones, and be the named reviewer for changes to it. This is the claim-an-ontology-category ask in D1-M1.
- Send us your column headers. A list of the headers in a typical lab spreadsheet (no data) is the best test of the resolver we have. We will report how many map, how many we refused and how many we got wrong.
- Verify your own papers. Look at the parameters we extracted from a paper you wrote and tell us which are wrong. Each correction is both a fix and a validation data point.
- Tell us what you already use. If your group, your instrument vendor or a repository you deposit in uses a vocabulary for units, materials or methods, tell us which, so we map to it rather than beside it.
- Try it from your assistant. Connect the MCP server, ask about a parameter in your own words, and tell us where it fell short.
How we will know it worked
The roadmap sets four targets that bear on this. The others are things we should measure but have set no target for, and the page does not invent one.
- Papers verified by their authorsRoadmap target
At least 5, in phase P1 (D1-M5).
- ISMET member accountsRoadmap target
At least 20, in phase P1 (D1-M5).
- External contributors or issues on the public packagesRoadmap target
At least 3, in phase P1 (D3-M3).
- Checklist endorsed or co-published with ISMETRoadmap target
In phase P2 (D1-M6).
- Share of real column headers the resolver maps correctlyOurs · no target set
Measured on headers partners send us, reported with the number it refused and the number it got wrong.
- Share of terms mapped to an external vocabularyOurs · no target set
Reported per layer, including the terms with no counterpart.
- Agreement between annotators, and with the pipelineOurs · no target set
On the same raw names, with the number of names and annotators stated.
- Distinct callers of the ontology toolsOurs · no target set
From the per-call usage line the server already logs, which keeps only a hashed caller key.
Where the figures come from
Each figure on this page comes from one of the sources below. The layer counts are from a dated audit; figures with a later date were measured on that date. The last column says how to check each one.
| Figure | Where it comes from | How to check it |
|---|---|---|
| Layer counts | Layer sizes and the slug and row counts: the staging audit in docs/onboarding/categorization-and-ontology.md (§5), dated under “What exists today”. | Re-measure on staging before quoting any of them. The audit’s “Lives in” column names the table or file behind each layer. |
| Definition counts | The 704, 825 and 835 definitions: the public package @messai-io/mess-parameters (704), the pinned parameter-definitions-rich.json (825) and the definitions table on staging (835). | Count each of the three. That they differ is the first item under “What is missing”. |
| The schema and the two traced names | Identifiers and repository counts: normalize-to-si.py, parameter-definitions-rich.json, the resolver fixtures, the run-01 classification and parameter-dag-edges-named-only.json. Staging counts (13 Oct 2026): Q14–Q16 in docs/collab/2026-10-12-staging-measurements.sql. | A test re-derives every repository value from those files and checks the diagram’s figures against the table above. Re-run Q14–Q16 for the staging counts. |
| MCP coverage | The 15 tools and what each layer reaches: apps/api/src/lib/mcp/tools.ts and apps/api/src/lib/mcp/resources.ts. | A test reads apps/api/src/lib/mcp/tools.ts and fails if a tool this page calls proposed is registered there, so the page cannot call a shipped tool proposed. scripts/routines/mcp-smoke.py, run against the live server, checks the live tools. |
| Roadmap dates | Dates and ids marked “roadmap”: docs/roadmap/2026-09-roadmap.md. | A test compares each roadmap date and milestone id on this page with that file. |
| Estimates | Working-day estimates and dates marked “proposed”: ours. None is scheduled and none is on the roadmap. | Nothing to check: they are proposals, to be replaced by dates once the work is planned. |
Open questions
- Which vocabulary should be the primary external anchor for each layer, and where do you already depend on one we have not named?
- Should the namespace live on messai.io, or somewhere neutral such as an ISMET domain, so that the ontology outlives the company?
- Is CC-BY-4.0, the licence of the public package, the right licence for the ontology itself?
- Four role vocabularies exist. Which distinction matters most to a lab reporting results: outcome versus condition, or driver versus intermediate?
- Who should be allowed to approve a term in a category: its steward alone, or the steward plus one reviewer from another group?
- Is an MCP tool for resolving terms enough, or should a write path exist for proposals, given that the server is read-only by design?