New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@mapled/mcp

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mapled/mcp

Mapled MCP server: lets AI agents build schema and content for one Mapled project.

npmnpm
Version
0.21.2
Version published
Weekly downloads
274
158.49%
Maintainers
1
Weekly downloads
 
Created
Source

@mapled/mcp

MCP server for Mapled — a hosted headless CMS built for sites created with AI. Connect it to Claude, Cursor, or any MCP-capable agent, and the agent can model collections, fill in content, and wire the site up end to end.

No agent at hand? Everything an agent does here can be done by a person: Integrate by hand in the @mapled/next README is the same integration, step by step.

Setup

The quickest way is the hosted endpoint with OAuth — no token to copy. In Claude Code:

claude mcp add --transport http mapled https://api.mapled.io/mcp

Your browser opens Mapled, you pick the project and authorize; the connection appears in Integrations and can be revoked there. Any MCP client that supports remote servers with OAuth (Claude Desktop, Cursor, ChatGPT) works the same way.

The local stdio server below is the alternative for clients without OAuth support.

Create a token in Mapled: project → Integrations → Connect with AI. Then add the server to your agent's MCP config:

{
  "mcpServers": {
    "mapled": {
      "command": "npx",
      "args": ["-y", "@mapled/mcp"],
      "env": { "MAPLED_MCP_TOKEN": "mcp_live_…" }
    }
  }
}

For Claude Code:

claude mcp add mapled -e MAPLED_MCP_TOKEN=mcp_live_… -- npx -y @mapled/mcp

The token is scoped to one project. Set MAPLED_API_URL only if you're not on the default https://api.mapled.io.

Over either transport, a refusal reaches the agent as Mapled words it — a key that is taken, a plan still waiting for approval, the slug it sent that another record already has. An error whose text carries anything shaped like a Mapled key or token that the call didn't send itself reaches it as one constant sentence instead: no tool answer, its errors included, hands the agent a secret.

Setting up a site

For the first integration, propose one plan and let the owner approve it on a trusted Mapled screen:

  • get_schema — see what already exists.
  • propose_setup_plan — the collections and singles (with fields and the records to import), the files you will change, the packages you will install. Nothing changes yet. Relation fields name their target — a collection of the plan by its display name, or an existing one by key; give a record a "$ref": "jane" and other records of the plan link to it as "author": "jane" (a list of refs for many), while links to existing collections use record ids from list_records. Group fields carry their sub-fields; their values are objects keyed by the sub-field keys. Mark a field — or a sub-field of a group — sensitive: true when editors keep it but the site must never get it. A link that does not resolve is answered right away with its path, so fix the plan before the owner sees it.
  • Ask the user to open the returned reviewUrl and approve. Poll get_setup_run until its status is approved (or rejected — then propose a better plan).
  • apply_setup_plan — Mapled creates everything in one go and tells you the keys it assigned.
  • Wire the site: get_connection, then configure_revalidation for a site with a server — or set_site_url for one rendered in the browser (a React single-page app, plain HTML: no webhook, no preview route) — and deploy. The webhook's signing secret never passes through the agent: the owner takes it from Mapled → Integrations → Your site, where Rotate secret shows a new one once, into the site's env as MAPLED_WEBHOOK_SECRET.
  • Leave a guide: get_mapled_md renders MAPLED.md from the project — what the site reads and where, the content model, the working rules, the commands that verify the integration. Write it to the repository root and commit it; the next agent (or person) starts from it. When the file exists, replace everything above its <!-- mapled:notes --> line and keep the notes below.
  • Close with report_setup (files changed, buildPassed, secretsCommitted: false, mapledMdWritten: true). Mapled runs its own checks — the site reads content, the webhook delivered, the preview route responds, fields have help texts, MAPLED.md was written — and the run is completed only when they pass. Fix what failed and call verify_setup. The result lands in the file's «Last setup run» section, so call get_mapled_md once more when the run is settled and commit the refreshed file.

Destructive and breaking changes

delete_collection, remove_field and clear_records never act on their own, and neither do the two breaking schema changes — rename_field (a field's key, what the site's code reads) and convert_field (its type, converting the stored values). Each one files a request and returns a reviewUrl: send it to the user, who confirms on a trusted Mapled screen by typing the name. Poll get_confirmation until the status is applied (the result says what changed), denied or expired (after an hour). Nothing changes until then.

A rename or a conversion Mapled wouldn't take is refused at once with the reason: a key that is taken or malformed, a type the field can't become, a formula that reads the field, values that can't be converted (with their count and examples — fix the content, or ask again with clearFailed: true; the person confirming sees how many will be cleared). After a rename the old key keeps working as an alias until a person removes it, so move the site's code to the new key first. Both can be undone from Field settings.

Tools

ToolWhat it does
propose_setup_plan / get_setup_run / apply_setup_plan / report_setup / verify_setupOne approved plan for the whole setup — every field type including relations ($ref handles between plan records, ids for existing collections) and groups — verified by Mapled (see above)
get_schemaRead the project's collections and fields, and its component types (componentTypes)
create_collectionAdd a collection or single
add_fieldAdd a field (short_text, long_text, rich_text, slug, image, number, boolean, date, datetime, relation, enum, url, email, group, file, color, json — an object or list up to 32 KB, location — { lat, lng }, computed, components). Optional validation ({min, max, pattern}) and defaultValue; relation ({target, cardinality: one | many, onDelete: restrict | nullify}) is required for relation fields — values are record ids of the target collection, kept in the order given; onDelete says what a delete of a linked record does (restrict: it can't be deleted while linked, nullify: the links are cleared — the default is restrict for required fields and nullify otherwise); options (1–50 labels) is required for enum fields; sensitive: true keeps a field out of lists, history and delivery (a group's sub-fields take it too); group ({fields, repeatable, maxItems}) shapes a group field — its values are objects (or arrays of them) keyed by the sub-field keys; components ({allowed, min, max}) makes a components field — an ordered list of blocks of the component types named in allowed (their keys, from add_component_type); values are lists of { _type, _key, …sub-fields }, _key given by Mapled and kept when sent back; computed ({expression}) makes a computed field — a formula Mapled evaluates whenever a record is read or published, over the record's fields and up to two links through relations (author.company.name, sum(items.product.price)) or back along one and one link on (count(@posts.author), sum(@order-items.order.product.price)), at most one list per path, never a sensitive field or relation; today() and now() are the moment the value was computed — baked at publish and recomputed once a day for the current release; the site reads the value like any field of its result type.
add_component_typeAdd a component type — a reusable block (hero, text, gallery…) for components fields: a name and the sub-fields an item holds (the types a group's sub-fields take, none sensitive, no relation or components inside); its key is what an item names in _type; types generate writes one TypeScript type per component and a components field as a union of them
list_templates / create_project_from_templateProject templates — Mapled's curated starting points (landing, blog, docs). The list gives each one's slug, name, description, starter-site repository and what it creates; creating makes a new project for the person who connected the client (theirs to own, on one of their plan's slots) with the template's collections, component types and sample records. region (us by default, or eu on a paid plan) says where the project's data is kept; it is chosen at creation and doesn't change. A template never applies to an existing project, and the connection keeps working only in the project it was made for — the answer says how to connect a client to the new one.
add_recordsInsert draft records — a translated field (localized: true in get_schema) by language, { "en": "About us", "ru": "О нас" }, or as one plain value, the default language's
list_recordsRead a collection's draft records, newest edit first — query searches their content as full text (every word, the last one from its start; best match first), limit (1–200) and cursor (the previous answer's nextCursor) page through them; total counts every match; locale reads the translated fields in one language (ru) or in every one at once (*, as { "en": …, "ru": … })
create_form / list_formsSet up public forms with spam protection
get_connectionThe delivery key and the API URL, plus — for the framework the agent names (nextjs, react-spa, plain-html, …) or the project's own — the package the site reads through (@mapled/next, @mapled/react, @mapled/vanilla — a script tag and data-mapled-* attributes for plain HTML — or @mapled/client), the env var of the key, whether the site renders on a server or in the browser, and the wire-up steps. Image values → assetUrl(id, { width }) of the same package
set_site_urlWhere the site is deployed — for a site rendered in the browser (a React single-page app, plain HTML), which has no webhook to learn it from: Preview opens the site there, verification checks that it answers
push_site_manifest / list_bindingsTell Mapled where each field is rendered; read every binding's health (type mismatch, outdated, missing on site). Keep the repository's copy in mapled/manifest.json — npx @mapled/cli scan --write derives it from the code and bindings push / bindings pull exchange it with Mapled. A push records the integration hash — the schema and these bindings — and list_bindings says whether it still matches (integration.inSync, with schemaChanged / bindingsChanged naming what moved). capabilities says whether open tabs follow Publish: { realtime: true, releaseRoute: "/api/mapled/release" } for a Next.js site with <MapledLive /> and createReleaseHandler (on the Pages Router, createPagesReleaseHandler), { realtime: true } for a site rendered in the browser whose tabs ask Mapled directly (live on MapledProvider, data-mapled-live on the script tag), { realtime: false } without live updates — only these two keys; MAPLED.md's Live updates line comes from it, so send it with every push
configure_revalidationPoint the publish webhook at the site (one with a server that caches what it reads). No answer carries the signing secret: it names the variable, MAPLED_WEBHOOK_SECRET, and the person takes the value from Mapled → Integrations → Your site, where Rotate secret shows a new one once, into the site's env. The description also tells the agent how to add live updates for tabs that are already open (createReleaseHandler and <MapledLive />, @mapled/next 0.8.0+; on the Pages Router createPagesReleaseHandler as an API route's default export and <MapledLive /> from @mapled/next/live/pages, 0.9.0+), declared then in the manifest's capabilities
check_integrationThe site's integration as Mapled sees it — delivery reads, the webhook and its last delivery, the bindings summary, the integration hash (is the last push still in step with the schema and the bindings?), current package versions; npx @mapled/cli doctor shows the same from inside the repository
list_workflows / get_workflowRead the project's workflows — the list (id, name, enabled, version, trigger, action types, problem) and one with its logic; webhook addresses come as their scheme only, and a workflow about a form's submissions or a signed-in users' collection comes without its logic (closed)
test_workflowTest a workflow on a record as a dry run — the steps a real event would take, what each would write or send — and nothing happens: no record changes, no email or webhook goes out. The owner's connection only; list_workflows gives the id
create_workflow / update_workflowMake or change a workflow in the shape get_workflow reads one (trigger, condition, up to 20 steps). Saved disabled, whatever the body says — a person turns it on in Mapled → Workflows; a change of the logic of a workflow that is on saves it off and the answer says so. Webhook addresses: a step sent back with its id and the address as shown keeps the saved one; a new address must be public. No signing secret ever; a workflow about a form's submissions, one reaching a signed-in users' collection or a step writing a sensitive field is refused. The owner's connection only
delete_collection / remove_field / clear_records / rename_field / convert_field / get_confirmationDestructive and breaking changes — each files a request a person confirms on a trusted Mapled screen (see above); get_confirmation reads its status
get_mapled_mdMAPLED.md rendered from the project — the guide for the next agent: project, how the site reads it, content model, bindings by page, last setup run, working rules, verification commands. Never a secret. npx @mapled/cli md pull writes the same file; mapled doctor says when it is out of date

Agents write drafts only — publishing stays with humans in the Mapled app, and nothing changes on the live site until someone presses Publish.

Keywords

mapled

FAQs

Package last updated on 06 Oct 2026

Related posts