Skip to content

Connecting an agent (MCP)

The hub exposes a Model Context Protocol endpoint at /hub/mcp, so an agent such as Claude can read and write your datasets without a browser.

Getting a token

The hub signs you in through your institution, which needs a browser; an agent is not a browser, so it presents a personal access token instead. Create one under Access tokens on your profile.

The token is shown once and cannot be recovered — only its hash is stored, so a copy of the database is not a set of working credentials. Create a new one if you lose it, and revoke any you no longer use.

A token can be given an expiry, after which it stops working on its own. A token without one lasts until revoked, which is what a token pasted into a config file and forgotten then does indefinitely.

A token acts as you. Every tool call is scoped to your own account: it can see and change your datasets and nothing else.

The endpoint also accepts an OIDC bearer — the access token your signed-in hub session already holds — for clients that can obtain one. A personal access token is the durable, non-interactive credential; the OIDC bearer expires with your session.

Configuring Claude Code

claude mcp add --transport http metaseed-hub https://metaseed.ewi.tudelft.nl/hub/mcp \
  --header "Authorization: Bearer msh_your_token_here"

What an agent can do

Tool
whoami Which account the token acts as
list_datasets Your datasets
get_dataset A dataset's stored contents
create_dataset A new, empty dataset
save_dataset Replace a dataset's contents
validate_dataset Check a dataset against its profile and list what is missing
delete_dataset Remove a dataset (soft — it is not erased)
list_profiles Built-in standards, plus every published specification
get_profile_schema A profile's entity types and their fields
get_profile_relationships A profile's hierarchy: each entity's identifier, children, and cross-references

Editing entities

Tool
create_entity Add one entity, without rewriting the dataset
batch_create Add several entities in one call, root-first; one version is kept for the whole batch
update_entity Change named fields; unnamed fields keep their values
delete_entity Remove one entity
list_entities The dataset's entities, with ids and values
get_entity One entity's stored values

Each of these reports what is still missing after the change, using the profile's own rules, so an agent can fill a dataset step by step instead of resending all of it. In a batch_create call, parent_index nests an item under an earlier item of the same batch, so a parent and its children can land together.

Building a specification

Tool
spec_create Start a new specification as a private draft
spec_import_yaml Start a new private draft from a YAML specification document
spec_clone Start a new private draft from a built-in profile or a published specification
spec_add_entity Add an entity type
spec_update_entity Change an entity's description or ontology term; unset arguments keep their values
spec_rename_entity Rename an entity, cascading the root and every reference to it
spec_delete_entity Remove an entity type
spec_add_field Add a field to an entity. items links a list or entity field to the child entity it nests; reference and parent_ref name cross-references; pattern, min_length, max_length, minimum, maximum, min_items, max_items, and enum constrain its values; the eighteen field markers declare what the field means
spec_update_field Change a field's attributes in place, items, reference, and parent_ref among them, plus the eight constraints, clear, and the eighteen field markers; unset arguments keep their values
spec_delete_field Remove a field
spec_move_field Move a field one position up or down
spec_add_rule Add a validation rule
spec_update_rule Change a validation rule in place
spec_delete_rule Remove a validation rule
spec_set_root_entity Set the entity a dataset starts from
spec_set_metadata Change the profile-level name, version, display name, description, or ontology
spec_status A summary of the draft: name, version, root, entities, rules
spec_validate What is wrong with the draft, under problems, and what merely looks unintended, under warnings
spec_preview_yaml The draft as YAML
list_spec_drafts Your drafts
spec_delete_draft Remove one of your own drafts

A specification is a tree: every entity except the root must be linked under a parent by a field on the parent whose type is list or entity and whose items names the child. An unlinked entity is an orphan a dataset can never reach, and spec_validate does not flag orphans. The endpoint's instructions carry this workflow (shared with the standalone metaseed MCP server), so connected agents link entities as they build.

Editing constraints

spec_update_field accepts the same eight constraints as spec_add_fieldpattern, min_length, max_length, minimum, maximum, min_items, max_items, enum — and merges them into the field's existing constraints. A constraint you do not supply keeps the value it had, so tightening maximum on a field that already has a minimum no longer discards the minimum.

Because an omitted argument means "unchanged", it cannot express removal. clear names the constraints to unset: clear=["pattern"] removes the pattern and leaves every other constraint alone. Setting and clearing the same constraint in one call is refused rather than resolved in some arbitrary order — the two requests contradict each other. The field is left untouched when a call is refused, including when a name is not one of the eight.

Field markers

A constraint says what values a field may hold; a marker says what the field is. Both spec_add_field and spec_update_field accept the eighteen markers metaseed's FieldSpec defines: is_identifier and is_label declare which field identifies the entity and which one labels it in listings, overriding the positional convention that would otherwise pick the first field; owns marks a containment relationship; and codename, ontologies, unique_within, dcat, example, options, unit, label, and tier carry the field's metadata. tier is one of required, recommended, or optional. For a profile bound to FAIRDOM-SEEK, isa_tag, within, reference_scope, seek_attribute_type, seek_controlled_vocab and seek_cv_free_text say which SEEK column a field becomes: its ISA tag, its attribute type, the controlled vocabulary it binds, and whether that vocabulary accepts free text.

A marker, unlike a numeric constraint, has a representable empty value, so it needs no clear: false, "", and [] are the removal request. An unset marker is absent from the specification rather than written as owns: false, so a draft that never touched a marker hashes the same as one that toggled it back off. A list marker is replaced whole, not merged. A value the schema refuses — a tier that is not one of the three levels, say — is reported and the field is left untouched, as it is when a constraint name is refused.

Adding a nested field with items also creates the parent's identifier field and a back-reference on the child, so the relationship is complete in both directions without further calls. spec_delete_draft removes a draft the caller owns; a draft a dataset is built on is not deleted, because the dataset would lose its specification.

Problems and warnings

spec_validate reports two lists. problems are defects: the draft does not build, and valid is false. warnings are advisory — an entity with no declared is_identifier whose identifier would be inferred onto an optional free-text field, for instance. A warning does not make a draft invalid, so valid stays true and problems stays empty; it names something worth deciding on before publishing.

Drafts are private to you. Publishing is not available to an agent — it shares a specification with every user of the hub, so it stays something you do yourself in the web interface.

Published specifications are included in list_profiles, because publishing shares a specification with every user of the hub — an agent can build a dataset against one it did not write.

Ontology lookups

Tool
search_ontology Search EMBL-EBI OLS4 for terms matching a query
get_ontology_term One term's definition and synonyms, by CURIE id
suggest_ontology_term Lighter suggestions for a partly typed term
list_ontologies The ontologies OLS4 offers, with their ids

These are read-only lookups against the Ontology Lookup Service, through the same cached, rate-limited service the web interface uses. They require a valid token — an open endpoint would let anyone drive traffic through the hub — but touch no dataset.

What an agent cannot do to your work

An agent replaces a whole dataset in one call, and can do it in a loop, so the write path is built to leave a way back:

  • Every overwrite keeps the previous contents as a version, restorable from the dataset's history in the web interface. A save that changes nothing adds no version, so repeated writes cannot bury the history.
  • Deleting is soft. The dataset stops being listed but is not erased.
  • A dataset larger than 5 MB is refused rather than stored, so a runaway loop is stopped.
  • An edit that would drop entities the hub could not read is refused. If a stored entity does not load — usually because the specification changed and no longer defines its type — it is missing from the dataset the agent sees, and saving over it would delete it. create_entity, update_entity, delete_entity and batch_create therefore refuse the whole dataset while that is true, naming how many entities are affected and of which types. validate_dataset lists them individually. save_dataset still works, because replacing the whole dataset is a deliberate act; use it only once you are content to lose them.
  • Every write is logged with the account it acted as.

A token reaches only its own user's datasets. Another person's dataset is not readable, writable, or deletable, and a name that exists in someone else's account reads as absent.

Using a token with the REST API

The same token authenticates the REST API at /api, so a script can do anything the web interface can:

curl -H "Authorization: Bearer msh_your_token" \
  https://metaseed.ewi.tudelft.nl/api/datasets

Three calls exist for a metaseed instance that pushes and pulls against the hub (see Pushing and pulling with metaseed-hub in the metaseed documentation): GET /api/me names the account and tenant the token acts in; GET /api/specs lists the published specifications and GET /api/specs/{name}/{version} returns one as a YAML profile document; POST /api/specs with {"yaml": "..."} pushes a profile into your account as a private draft — only you see it, and pushing a revised document updates it in place; {"yaml": "...", "publish": true} publishes it for every hub user instead, under the same version-bump gate the spec builder applies (identical content already published answers 200; a version taken by different content, or below what the change requires, answers 409 with the reason). POST /api/specs/{id}/unpublish withdraws a published specification back to a private draft, with the same permissions as the Unpublish button. Each entry GET /api/specs lists carries visibility (draft or published) and mine. GET, POST and PATCH on /api/datasets carry datasets both ways.

The hub accepts exactly two credentials: a SRAM access token, which a browser obtains through the sign-in flow, and a token from this page. A token acts for your own data only and never carries administrator rights, whatever your account holds.

Revoking access

Revoke a token from your profile. It stops working immediately; the record is kept so an administrator can see that it existed and when it was withdrawn.