Open History Map Tools harris-mcp
Plate №.8DEE

harris-mcp

Harris matrices as structured context for language models: a Model Context Protocol server that loads stratigraphy from the formats archaeologists use, lets a model query it as a graph, and records every interpretive edit on a changelog a person can audit.

§1 · The split

Graph work happens on the server, interpretation on the model, and every edit lands on a changelog.

Server
Parsing, validation, ordering, candidate matching and consistency checks. Deterministic and tested.
Model
Proposes phasings and correspondences from dense, structured reads rather than from a screenshot of the diagram.
Person
Reads the changelog, where every edit carries a note and an author, then keeps, diffs or reverts it.

§2 · Quick start

Use the public instance

Any MCP client that speaks SSE can connect. With Claude Code:

claude mcp add --transport sse harris \
  https://harris.openhistorymap.org/mcp/sse

The public instance has no authentication and keeps matrices in memory. Do not load unpublished project data there; run your own.

Run your own

docker build -t harris-mcp .
docker run --rm -p 8000:8000 -v "$PWD/data:/data:ro" harris-mcp
# MCP endpoint: http://localhost:8000/mcp/sse   health: GET /

A first session

  1. Open or upload a matrix

    open_matrix("/data/fig12") opens a file on the server; upload_matrix(files={"site.hmcx": …}, encoding="base64") sends your own. Either returns a handle, its size, depth and a validation report; an upload also returns the inferred phase order and any anomalies.

  2. Read it densely

    describe_context(id, "15") returns the unit, its neighbours above and below, its phase and any links to other records.

  3. Edit with a reason

    assign_phase(id, "9", "Phase II", note="C14 LAB-1 fits the lower phase") lands on history.

  4. Save

    save_matrix(id, "fig12.hmdp.json") keeps the changelog with the matrix.

§3 · Formats

HMDP, an open JSON package defined here, is the pivot: every adapter reads into it and writes out of it.

FormatReadWriteNotes
HMDP .jsonyesyesCanonical and lossless, including the changelog
CSV, XLSXyesyescontexts and relations tables, or an above/below edge list
hm tables (T. S. Dye)yesnoFrictionless datapackage.json or an hm .ini project, a folder or a .zip
HMCX (Harris Matrix Composer)yesnoGraphML inside a zip; phase and period groups become attributes
HMC CSV exportyesnoSemicolon file starting HEADER;, Latin-1 tolerated

Every relation verb is canonicalised: above, below, cuts and fills become edges of a directed acyclic graph from upper to lower unit; equal and contemporary join a union-find class. The original verb stays on the relation.

§4 · Tool reference

Reads return interpretively useful chunks rather than one attribute per call; every write is recorded on the matrix's changelog with a note and an author. The list below is generated from the server by docs/gen_reference.py.

Load and save 6

open_matrix
Load a Harris matrix file on the server and return its handle.
upload_matrix
Upload a matrix by content, open it, and return a first analysis.
open_corpus
Load several matrix files at once.
close_matrix
Close an open matrix and free it from the registry.
list_open_matrices
Summaries of every open matrix: id, name, size, depth.
save_matrix
Write a matrix to path (format from the extension, or fmt).

Read units 4

get_context
One context (unit) with all its fields and attributes.
list_contexts
Contexts filtered by phase, period, type, group or geometry.
count_contexts
Number of contexts per phase, period, type or group.
search_contexts
Substring (case-insensitive) match across id, description, and attrs.

Read relations 7

neighbors
Units directly above, below or contemporary with ctx, up to depth steps.
ancestors
All units stratigraphically earlier than ctx (transitive): below it.
descendants
All units stratigraphically later than ctx (transitive): above it.
relation
Return the stratigraphic relationship between a and b.
path
Shortest stratigraphic path from a to b, or null if unordered.
between
Units strictly between two contexts on the partial order.
contemporaries
Units recorded as the same as, or contemporary with, ctx.

Whole matrix 11

topological_layers
The Harris layout: contexts grouped by topological generation, earliest first.
phases
Every phase and its member contexts.
phase_sequence
Phase order implied by the stratigraphy, earliest first.
periods
Every period and its member contexts.
phase_contexts
Contexts of one phase, in stratigraphic order (latest first).
validate
Structural diagnostics: cycles, dangling references, redundant edges, orphans.
summary
Size, depth and changelog length of an open matrix.
anomalies
Phase assignments that violate the stratigraphic partial order.
describe_context
High-density read: context + neighborhood + phase + correspondences.
describe_phase
High-density read of a phase: members, units bordering it above and below, anomalies.
boundary_contexts
Contexts in phase that touch units outside the phase.

Edit (changelogged) 8

add_context
Add a context.
update_context
Patch fields of a context.
delete_context
Delete a context and its relations.
add_relation
Add a relation (above, below, cuts, fills, equal, contemporary, ...).
remove_relation
Remove a relation between a and b (optionally only of kind).
assign_phase
Set the phase of a context.
mark_contemporary
Record two contexts as contemporary.
attach_note
Append a free-form interpretive note to a context's attrs.notes list.

Provenance 3

history
The changelog of a matrix, oldest first: op, arguments, note, author, time.
revert
Mark a changelog entry as reverted and undo its effect.
diff
Return the changelog slice between two entry ids (inclusive).

Cross-document 8

query_corpus
Search across every open matrix.
cross_reference
Suggest candidate matches between two matrices, best first.
propose_reconciliation
Propose which units of matrix_a and matrix_b are the same unit.
assert_correspondence
Record a cross-document correspondence — the LLM's interpretive conclusion.
check_correspondences
Merge matrices through their same_as correspondences and report stratigraphic contradictions: groups of units that end up both above and below one another, with the correspondences involved.
correspondences
Asserted cross-document correspondences, optionally for one matrix or context.
compare_phases
Phases shared by two matrices and those found in only one, with sizes.
compare_periods
Periods shared by two matrices and those found in only one.

Output 4

render
Render the matrix.
subgraph
Local stratigraphy around roots, as an HMDP-shaped subset.
export_geojson
FeatureCollection of contexts that carry geometry.
link_ohm_feature
Record a cross-reference from a stratigraphic context to an Open History Map feature id.

Resources 7

  • harris://corpus/correspondences
  • harris://matrices
  • harris://matrix/{matrix_id}/context/{ctx}
  • harris://matrix/{matrix_id}/context/{ctx}/describe
  • harris://matrix/{matrix_id}/diagnostics
  • harris://matrix/{matrix_id}/layers
  • harris://matrix/{matrix_id}/summary

§5 · Reconciling units across records

When two teams record the same deposits, which of their units are the same unit? propose_reconciliation answers in three layers and writes nothing:

  1. Candidates

    Description similarity, compared only between units of the same period and type.

  2. Structural agreement

    A match scores higher when its matched neighbours sit on the same side, above or below; the matching is refined over a few rounds.

  3. Cycle refusal

    A match whose merge would put a unit both above and below another is rejected and listed.

The model or a person then records conclusions with assert_correspondence, which reports any contradiction it introduces; check_correspondences audits the whole set.

Evaluation

A simulation takes Cessford's Çatalhöyük Buildings 1 and 5 matrix (705 units, 852 relations) as ground truth. Two simulated teams record overlapping parts of it with their own numbering, noisy descriptions, missed relations and split or merged units. Four reconcilers, a cumulative ablation of the tool, are scored against the truth, all through the MCP interface.

0.83 vs 0.67F1, structure vs period/type filter · trench · 20% noise
0.68 vs 0.40The same · full re-recording of 705 units
0 vs 1,317Units in a contradiction · cycle check vs text alone
Fig. 1 F1 of recovered same-as pairsMean ± sd 10 seedsDropout 10%
OverlapNoiseDropout text + period/type + cycle check + structure
trench0%10% 0.32 ± 0.02530 in cycles 0.95 ± 0.021 in cycles 0.95 ± 0.020 in cycles 0.96 ± 0.020 in cycles
trench20%10% 0.13 ± 0.01579 in cycles 0.67 ± 0.0633 in cycles 0.70 ± 0.070 in cycles 0.83 ± 0.050 in cycles
trench40%10% 0.05 ± 0.02591 in cycles 0.37 ± 0.0968 in cycles 0.38 ± 0.090 in cycles 0.52 ± 0.140 in cycles
trench40%30% 0.05 ± 0.02230 in cycles 0.37 ± 0.0924 in cycles 0.37 ± 0.090 in cycles 0.42 ± 0.100 in cycles
full0%10% 0.80 ± 0.011,028 in cycles 0.84 ± 0.01850 in cycles 0.84 ± 0.020 in cycles 0.93 ± 0.010 in cycles
full20%10% 0.29 ± 0.021,287 in cycles 0.40 ± 0.021,202 in cycles 0.43 ± 0.020 in cycles 0.68 ± 0.030 in cycles
full40%10% 0.09 ± 0.011,317 in cycles 0.15 ± 0.011,273 in cycles 0.16 ± 0.020 in cycles 0.25 ± 0.030 in cycles
full40%30% 0.09 ± 0.01998 in cycles 0.15 ± 0.01910 in cycles 0.16 ± 0.010 in cycles 0.22 ± 0.030 in cycles

F1, mean ± sd over seeds; below it, units caught in a stratigraphic contradiction after merging. Best F1 per row in bold.

Descriptions are synthetic and both teams share period names, which flatters the period filter. Design, caveats and reproduction steps are in sim/README.md; the raw data in sim/results/.

§6 · Datasets used

DatasetSourceLicence
Harris, fig. 12E. C. Harris, as packaged by T. S. Dyesee source
Çatalhöyük East Mound, Buildings 1 and 5Matrix by C. Cessford, via T. S. Dye's hm examplesGPL-3.0
Ulm-EggingenE. Rosenstock, Linear Pottery and Harris (2022), doi:10.5281/zenodo.5534232CC BY 4.0