---
title: "MCP server"
description: "Connect AI assistants to CoreModels over the Model Context Protocol. Read-only tools for search, export, validation, and schema transform."
slug: "mcp-server"
type: page
locale: en-US
canonical: "https://www.coremodels.io/mcp-server"
updatedAt: "2026-10-24T15:27:54Z"
---

# MCP server

## CoreModels MCP Server

Connect your AI assistant to a governed model. With Admin access, agents import and update the model. On every connection, they validate payloads, transform formats and export schemas — without pasting the contract into the prompt.

On this page

- [Overview](#overview)
- [Quick Start](#quick-start)
- [Usage Examples](#usage-examples)
- [Agent Skills](#agent-skills)
- [Capabilities](#capabilities)
- [FAQ](#faq)

[Open CoreModels](https://go.coremodels.io/app)

## Overview

The CoreModels MCP (Model Context Protocol) server lets AI agents talk to your projects directly. Point Cursor, Claude Code, or another MCP client at `https://go.coremodels.io/mcp` for read-only tools, or `https://go.coremodels.io/mcp-admin` when the agent needs write access. Either way, the assistant queries the model your team governs instead of inventing a schema from memory. With the admin server, an agent can import [what dbt writes](/connector/dbt), audit drift in CI, answer what breaks and write the contract back.

## Quick Start

Follow these steps to connect a client. Both endpoints are authenticated. Start with the read-only server unless the agent needs to write.

1

### Get an API key

Sign in to CoreModels and generate a personal API key from account settings. Spec-compliant clients such as Claude Code can complete OAuth instead and do not need a key pasted into config.

- Open CoreModels and sign in
- Go to account settings
- Generate a new API key

[Open CoreModels](https://go.coremodels.io/app)

A key authenticates who is asking. Write tools on the admin endpoint still require Admin membership on the project.

2

### Configure your client

Choose your AI client and add the CoreModels server.

**Cursor**

[One-click install (read-only) in Cursor →](https://cursor.com/en/install-mcp?name=coremodels&config=eyJ1cmwiOiJodHRwczovL2dvLmNvcmVtb2RlbHMuaW8vbWNwIn0=)

Or add this to your `mcp.json`. Use the admin block only when the agent should be allowed to write.

**Read-only**

```
{
  "mcpServers": {
    "coremodels": {
      "url": "https://go.coremodels.io/mcp",
      "headers": {
        "Authorization": "Bearer <your CoreModels API key>"
      }
    }
  }
}
```

**Admin**

```
{
  "mcpServers": {
    "coremodels-admin": {
      "url": "https://go.coremodels.io/mcp-admin",
      "headers": {
        "Authorization": "Bearer <your CoreModels API key>"
      }
    }
  }
}
```

**Claude Code**

Add the HTTP server, then complete OAuth when the client prompts you. Add the admin server only if the agent needs write tools.

**Read-only**

```
claude mcp add --transport http coremodels https://go.coremodels.io/mcp
```

**Admin**

```
claude mcp add --transport http coremodels-admin https://go.coremodels.io/mcp-admin
```

**Other MCP clients**

Use a bearer API key, or OAuth if your client supports the current MCP spec. Point read-only clients at `https://go.coremodels.io/mcp` and write clients at `https://go.coremodels.io/mcp-admin`.

**Read-only URL**

```
https://go.coremodels.io/mcp
```

**Admin URL**

```
https://go.coremodels.io/mcp-admin
```

**Read-only config**

```
{
  "mcpServers": {
    "coremodels": {
      "url": "https://go.coremodels.io/mcp",
      "headers": {
        "Authorization": "Bearer <your CoreModels API key>"
      }
    }
  }
}
```

**Admin config**

```
{
  "mcpServers": {
    "coremodels-admin": {
      "url": "https://go.coremodels.io/mcp-admin",
      "headers": {
        "Authorization": "Bearer <your CoreModels API key>"
      }
    }
  }
}
```

## Usage Examples

Practical prompts once the server is connected.

### Search the governed model

Ask your assistant to find projects, types, and fields instead of guessing from training data:

```
List my CoreModels projects.

Summarize the types, elements, and taxonomies in this project.

Search for nodes named "customer" and show the types that use them.
```

### Transform a schema

Hand a source schema to transform_schema and get the target format plus what the conversion lost:

```
Transform this JSON Schema to Avro with transform_schema.

Convert our Customer JSON Schema to Postgres DDL.

Take this proto3 file and give me the JSON Schema, and tell me what we lose.
```

### Validate a payload

Check a document against a type in the project — the same schema the exports come from:

```
Validate this JSON document against type Customer in this project.

Does this payload fit BiospecimenTemplate? If not, name the failing fields.
```

### Identify a schema

Match a sample to a type without committing when the input is under-determined:

```
Which type in this project matches this JSON sample?
Enumerate every candidate before you commit.

These three identifier fields appear on many templates — which type did I mean?
```

### Write with the admin server

Connect to the admin endpoint when the agent should import or change a project. These tools are not on the read-only server:

```
Import this dbt manifest into project <id>.

Add this JSON Schema as a new type in the project.

Run the vendor audit on these artifacts, then import only if the report is clean.
```

## Agent Skills

Add this ready-made skill to your AI client for an expert workflow on top of the MCP server.

### schema-identification

Match a JSON sample to the right type in a CoreModels project — enumerate every candidate and narrow when the sample is under-determined instead of guessing. Uses `get_project_summary`, `search_nodes`, `export_jsonschema`, and `validate_json`.

[Download](/skills/schema-identification/SKILL.md)

#### Install locally

Save the file as `SKILL.md` inside a folder named after the skill so your AI client can discover it:

Cursor

```
.cursor/skills/schema-identification/SKILL.md
```

Claude Code / Claude Desktop

```
~/.claude/skills/schema-identification/SKILL.md
```

This skill calls the CoreModels MCP tools. Configure the server in Quick Start first so it can use `search_nodes` and `validate_json`.

#### Skill contents

```
---
name: schema-identification
description: >-
  Identify which schema/type in a CoreModels project best matches a JSON data
  sample — and, crucially, refuse or narrow when the sample is under-determined
  instead of guessing. Use when a user provides a data record, payload, or set of
  fields and asks "what schema/type is this?", "which model does this fit?", or
  wants a sample validated against a CoreModels project.
---

# Schema Identification with CoreModels

You are matching a JSON data sample to the types defined in a CoreModels project
(a typed schema graph). A project has **types** (classes/schemas), **elements**
(fields, shared across types), and **taxonomies** (controlled-vocabulary value
sets). A type is linked to each of its fields by a **"Domain Includes"** relation.

## The one rule that matters most

**Enumerate every candidate before you commit.** The graph makes it easy to find
*a* type that contains a field and stop there — that is the main way this task goes
wrong. A field almost never belongs to only one type. You have not identified a
schema until you have checked which *other* types also contain *all* the sample's
fields. Finding that `TypeX` contains all the fields is **not** sufficient; you must
also confirm no other type does.

## Tools

- `get_project_summary` — list the project's types, elements, taxonomies (labels +
  ids). Orient here first. It paginates; page through if needed.
- `search_nodes` — find a specific element or type by name/text.
- `get_mixins_and_relation_groups` — see the relation groups (including
  "Domain Includes" that ties a type to its fields).
- `export_jsonschema` — export a candidate type's full JSON Schema.
- `validate_json` — validate the sample against a specific type. Use this to
  confirm a commit, not to search.

## Method

1. **Extract the fields.** List the top-level keys of the sample. Note any nested
   objects and any `_type`/discriminator hints (but do not trust a discriminator
   blindly — verify it).
2. **Map each field to its element(s).** For each field, `search_nodes` to find the
   matching element node and record its id.
3. **Find the types that include each field.** For each element, look at its
   "Domain Includes" relations to collect the set of types that contain it. (A
   type's outgoing "Domain Includes" = its field list; an element's incoming ones =
   the types that use it.)
4. **Intersect.** The candidate set is the types that contain **all** the sample's
   fields — the intersection of the per-field type sets. This intersection is the
   answer to "how determined is this sample", so compute it explicitly. Do not skip
   it because one type looked right.
5. **Check values, not just field names.** If a field maps to a taxonomy
   (controlled vocabulary), confirm the sample's value is actually in that taxonomy.
   A field-name match with an out-of-vocabulary value is a weaker match and may rule
   a type out.
6. **Resolve reference-behind disambiguators.** If two candidates share every
   top-level field but differ in the *type* of a nested field (e.g. one expects
   `data` to be a `HISTORY`, another an `ITEM_STRUCTURE`), export those types and
   compare the nested structure to disambiguate. If the sample doesn't carry enough
   nested detail to decide, it stays under-determined — say so.

## Decision rule

- **Exactly one candidate** contains all fields (and values check out): **commit.**
  Name the type, cite its node id, and validate with `validate_json`.
- **More than one candidate:** **do not pick one.** Return the candidate list and
  name the specific field or value that *would* disambiguate ("add `state` to
  distinguish OBSERVATION; provide `bodySite` to distinguish BiospecimenTemplate").
  Ask for it or state plainly that the input is under-determined.
- **No candidate** contains all fields: say there is no matching type in the
  project. Do not invent one, and do not force-fit the closest partial match.

Prefer under-claiming to over-claiming. "These three types all fit; I need X to
choose" is a correct and useful answer — a confident wrong commit is not.

## Worked example

Sample: `{ "individualID": ..., "specimenID": ..., "aliquotID": ... }`

1. Fields: individualID, specimenID, aliquotID.
2. `search_nodes` finds each as an element.
3. "Domain Includes" relations show **individualID** is used by BiospecimenTemplate
   *and* ~28 assay templates; likewise specimenID and aliquotID.
4. Intersection = ~29 types. **Under-determined.**
5. Correct answer: *"These are shared identifier fields present in ~29 templates
   (BiospecimenTemplate plus assay templates). There is no field here that selects
   one — e.g. `bodySite` would point to BiospecimenTemplate, an assay-specific field
   would point elsewhere. Which did you intend?"*
   A commit to BiospecimenTemplate here would be wrong, even though it is the most
   familiar match.

## Failure modes to avoid

- **Satisficing:** committing to the first type that contains the fields without
  checking the others. This is the most common error — the enumeration step exists
  to prevent it.
- **Committing through visible ambiguity:** if you have already seen that several
  types match, listing them and then committing to one anyway is the same error.
- **Answering from memory:** if the tools fail or return nothing, say so and stop —
  never fall back to what you "know" the schema probably is.
- **Trusting a discriminator you didn't verify:** a `_type` hint can be absent,
  wrong, or ambiguous; confirm against the project.
```

## Capabilities

### Search and discovery

List the projects you can see, search nodes by name, and read detailed type, element, and taxonomy information from the governed model.

### Project inspection

Pull a project summary, inspect mixins and relation groups, and walk Domain Includes so an agent can see which fields belong to which types.

### Transform and export

Convert between JSON Schema, Avro, SQL, LinkML, ShEx, JSON-LD, OWL, Protocol Buffers, ODCS and more, or export a stored type as JSON Schema.

### Validation

Validate a JSON document against a type in the project. The check uses the live model, not a copy saved to a laptop last quarter.

### Admin writes

The admin endpoint adds write tools — import, update, and other mutations — behind Admin membership on the project. Read tools stay on the read-only server; write tools need a second, explicit connection.

## Frequently Asked Questions

### What is MCP?

Model Context Protocol is an open standard that lets AI assistants call tools and read data from systems you connect. The CoreModels MCP server gives an agent a typed, authenticated interface to a governed model.

### Do I need an API key to search?

The published endpoint is authenticated. Use a CoreModels API key as a bearer token, or complete OAuth in a spec-compliant client such as Claude Code. There is no public, unauthenticated demo endpoint.

### Can I use the same API key in more than one assistant?

Yes. For security, prefer a different key per environment or client when you can.

### What happens if I lose my API key?

Generate a new key from your CoreModels account. Update every client that still holds the old one.

### Can an agent create or update projects over MCP?

Use https://go.coremodels.io/mcp for read-only tools: list, search, export, validate, and transform. Write tools live on https://go.coremodels.io/mcp-admin and require Admin membership on the project. A bearer key or OAuth token is still checked against that role.

### Can I export a project from the MCP server?

Yes. Export and transform tools return machine-readable schemas. You can also export through the CoreModels app and the HTTP API.

## Ready to get started?

Open CoreModels, connect an assistant, and let it work on the model your team already governs.

[Open CoreModels](https://go.coremodels.io/app)[See pricing](/pricing)

[Want us to build one over your own systems? See agent-ready services](/agent-ready)
