@mapled/mcp 0.18.2 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -66,8 +66,8 @@ A rename or a conversion Mapled wouldn't take is refused at once with the reason
66
66
  | `get_schema` | Read the project's collections and fields |
67
67
  | `create_collection` | Add a collection or single |
68
68
  | `add_field` | Add 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). 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; `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. |
69
- | `add_records` | Insert draft records |
70
- | `list_records` | Read a collection's draft records, newest edit first — `query` searches their content, `limit` (1–200) and `cursor` (the previous answer's `nextCursor`) page through them; `total` counts every match |
69
+ | `add_records` | Insert 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 |
70
+ | `list_records` | Read a collection's draft records, newest edit first — `query` searches their content, `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": … }`) |
71
71
  | `create_form` / `list_forms` | Set up public forms with spam protection |
72
72
  | `get_connection` | The 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 |
73
73
  | `set_site_url` | Where 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 |
package/dist/tools.js CHANGED
@@ -458,6 +458,13 @@ export function createTools(api) {
458
458
  "script tag) sends { realtime: true }; a site without live updates sends { realtime: false }. Only these two keys " +
459
459
  "are accepted. Nothing is graded by them and they stay out of the integration hash, but MAPLED.md's " +
460
460
  "Live updates line comes from them — send them with every push, as a push without them drops the line. " +
461
+ "`locales` says how the routes carry the language on a site with more than one (§28.4): " +
462
+ "{ routing: \"prefix\", param: \"locale\" } when every language lives under its own segment " +
463
+ "(/[locale]/blog/[slug] — the page routes keep the segment), { routing: \"prefix-except-default\" } when the " +
464
+ "default language is at the root and the others under /ru/…, /de/… (without `param` Mapled puts the language " +
465
+ "before the page). Mapled builds each language's address of a record from it (the editor's routes, Preview); " +
466
+ "a translated slug is the address in that language, a missing translation falls back. Leave it out on a " +
467
+ "site with one address for every language. " +
461
468
  "The answer's manifest.integrationHash is the hash of the schema and these " +
462
469
  "bindings — what the site is synced with from now on; check_integration reports inSync against it. " +
463
470
  "Needs the builder plan.",
@@ -499,6 +506,15 @@ export function createTools(api) {
499
506
  .strict()
500
507
  .optional()
501
508
  .describe("Whether open tabs follow a publish: realtime, and releaseRoute — the path of the site's release route, e.g. /api/mapled/release."),
509
+ // routes by language (§28.4), the API's shape (lib/bindings.ts): strict
510
+ locales: z
511
+ .object({
512
+ routing: z.enum(["prefix", "prefix-except-default"]),
513
+ param: z.string().regex(/^[A-Za-z0-9_-]{1,60}$/).optional(),
514
+ })
515
+ .strict()
516
+ .optional()
517
+ .describe("How the routes carry the language: routing — prefix (every language under its own) or prefix-except-default (the default at the root); param — the dynamic segment that holds it, e.g. locale for /[locale]/blog/[slug]."),
502
518
  },
503
519
  handler: async (args) => api.request("POST", "/v1/agent/manifest", args),
504
520
  },
@@ -616,7 +632,8 @@ export function createTools(api) {
616
632
  },
617
633
  {
618
634
  name: "add_records",
619
- description: "Insert up to 100 records into a collection. Each record maps field keys to values (rich_text takes Markdown; image takes an asset id; relation takes record ids; group takes objects).",
635
+ description: "Insert up to 100 records into a collection. Each record maps field keys to values (rich_text takes Markdown; image takes an asset id; relation takes record ids; group takes objects). " +
636
+ 'A translated field (`localized: true` in get_schema) takes its values by language — { "en": "About us", "ru": "О нас" }; give the default language, it is what the site shows where a translation is missing — or one plain value, which is the default language\'s; a translated slug is unique within its language.',
620
637
  schema: {
621
638
  collectionKey: z.string().min(1).max(120),
622
639
  records: z.array(z.record(z.string(), z.unknown())).min(1).max(100),
@@ -644,12 +661,14 @@ export function createTools(api) {
644
661
  },
645
662
  {
646
663
  name: "list_records",
647
- description: "List a collection's draft records (id, title, data), most recently edited first — up to `limit` per page (200 by default). `query` narrows the list to records whose content contains it; when the answer carries nextCursor, pass it as `cursor` for the next page. `total` counts every match.",
664
+ description: "List a collection's draft records (id, title, data), most recently edited first — up to `limit` per page (200 by default). `query` narrows the list to records whose content contains it; when the answer carries nextCursor, pass it as `cursor` for the next page. `total` counts every match. " +
665
+ "`locale` reads the translated fields in one language (a code such as ru — a field with no value in that language is left out) or, with *, in every language at once as { \"<code>\": value }; without it the default language, as always.",
648
666
  schema: {
649
667
  collectionKey: z.string().min(1).max(120),
650
668
  query: z.string().max(200).optional().describe("Text to search for in the records' content."),
651
669
  limit: z.number().int().min(1).max(200).optional().describe("Records per page, 1–200 (default 200)."),
652
670
  cursor: z.string().max(200).optional().describe("nextCursor from the previous page."),
671
+ locale: z.string().max(40).optional().describe("A language code such as ru or pt-BR, or * for every language at once."),
653
672
  },
654
673
  handler: async (args) => {
655
674
  const params = new URLSearchParams();
@@ -659,6 +678,8 @@ export function createTools(api) {
659
678
  params.set("limit", String(args.limit));
660
679
  if (args.cursor)
661
680
  params.set("cursor", args.cursor);
681
+ if (args.locale)
682
+ params.set("locale", args.locale);
662
683
  const qs = params.toString();
663
684
  return api.request("GET", `/v1/agent/collections/${encodeURIComponent(args.collectionKey)}/records${qs ? `?${qs}` : ""}`);
664
685
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapled/mcp",
3
- "version": "0.18.2",
3
+ "version": "0.19.0",
4
4
  "description": "Mapled MCP server: lets AI agents build schema and content for one Mapled project.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://mapled.io",