emdash 0.8.0 → 0.10.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/dist/{adapters-BKSf3T9R.d.mts → adapters-BktHA7EO.d.mts} +1 -1
- package/dist/{adapters-BKSf3T9R.d.mts.map → adapters-BktHA7EO.d.mts.map} +1 -1
- package/dist/{apply-x0eMK1lX.mjs → apply-UsrFuO7l.mjs} +207 -355
- package/dist/apply-UsrFuO7l.mjs.map +1 -0
- package/dist/astro/index.d.mts +6 -6
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +118 -4
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +6 -7
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +14 -57
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/redirect.d.mts.map +1 -1
- package/dist/astro/middleware/redirect.mjs +15 -10
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.d.mts.map +1 -1
- package/dist/astro/middleware/request-context.mjs +8 -5
- package/dist/astro/middleware/request-context.mjs.map +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +70 -121
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/types.d.mts +25 -10
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/{byline-Chbr2GoP.mjs → byline-C3vnhIpU.mjs} +4 -4
- package/dist/{byline-Chbr2GoP.mjs.map → byline-C3vnhIpU.mjs.map} +1 -1
- package/dist/bylines-esI7ioa9.mjs +113 -0
- package/dist/bylines-esI7ioa9.mjs.map +1 -0
- package/dist/cache-fTzxgMFJ.mjs +65 -0
- package/dist/cache-fTzxgMFJ.mjs.map +1 -0
- package/dist/{chunks-HGz06Soa.mjs → chunks-Da2-b-oA.mjs} +8 -2
- package/dist/{chunks-HGz06Soa.mjs.map → chunks-Da2-b-oA.mjs.map} +1 -1
- package/dist/cli/index.mjs +456 -90
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.mjs +3 -3
- package/dist/client/index.mjs.map +1 -1
- package/dist/{config-BXwuX8Bx.mjs → config-CVssduLe.mjs} +1 -1
- package/dist/{config-BXwuX8Bx.mjs.map → config-CVssduLe.mjs.map} +1 -1
- package/dist/{content-BcQPYxdV.mjs → content-C7G4QXkK.mjs} +42 -14
- package/dist/content-C7G4QXkK.mjs.map +1 -0
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/libsql.d.mts.map +1 -1
- package/dist/db/libsql.mjs +7 -2
- package/dist/db/libsql.mjs.map +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.d.mts.map +1 -1
- package/dist/db/sqlite.mjs +8 -3
- package/dist/db/sqlite.mjs.map +1 -1
- package/dist/{db-errors-l1Qh2RPR.mjs → db-errors-B7P2pSCn.mjs} +1 -1
- package/dist/{db-errors-l1Qh2RPR.mjs.map → db-errors-B7P2pSCn.mjs.map} +1 -1
- package/dist/{default-DCVqE5ib.mjs → default-pHuz9WF6.mjs} +1 -1
- package/dist/{default-DCVqE5ib.mjs.map → default-pHuz9WF6.mjs.map} +1 -1
- package/dist/{dialect-helpers-DhTzaUxP.mjs → dialect-helpers-BKCvISIQ.mjs} +19 -2
- package/dist/dialect-helpers-BKCvISIQ.mjs.map +1 -0
- package/dist/{error-zG5T1UGA.mjs → error-DqnRMM5z.mjs} +1 -1
- package/dist/{error-zG5T1UGA.mjs.map → error-DqnRMM5z.mjs.map} +1 -1
- package/dist/{index-DIb-CzNx.d.mts → index-DjPMOfO0.d.mts} +162 -87
- package/dist/index-DjPMOfO0.d.mts.map +1 -0
- package/dist/index.d.mts +11 -11
- package/dist/index.mjs +27 -24
- package/dist/{load-CyEoextb.mjs → load-sXRuM7Us.mjs} +2 -2
- package/dist/{load-CyEoextb.mjs.map → load-sXRuM7Us.mjs.map} +1 -1
- package/dist/{loader-CndGj8kM.mjs → loader-Bx2_9-5e.mjs} +53 -8
- package/dist/loader-Bx2_9-5e.mjs.map +1 -0
- package/dist/{manifest-schema-DH9xhc6t.mjs → manifest-schema-CXAbd1vH.mjs} +33 -3
- package/dist/manifest-schema-CXAbd1vH.mjs.map +1 -0
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +1 -1
- package/dist/media/local-runtime.d.mts +7 -7
- package/dist/{mode-BnAOqItE.mjs → mode-YhqNVef_.mjs} +1 -1
- package/dist/{mode-BnAOqItE.mjs.map → mode-YhqNVef_.mjs.map} +1 -1
- package/dist/options-nPxWnrya.mjs +117 -0
- package/dist/options-nPxWnrya.mjs.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/{patterns-CrCYkMBb.mjs → patterns-DsUZ4uxI.mjs} +1 -1
- package/dist/{patterns-CrCYkMBb.mjs.map → patterns-DsUZ4uxI.mjs.map} +1 -1
- package/dist/{placeholder-D29tWZ7o.d.mts → placeholder-CDPtkelt.d.mts} +1 -1
- package/dist/{placeholder-D29tWZ7o.d.mts.map → placeholder-CDPtkelt.d.mts.map} +1 -1
- package/dist/{placeholder-C-fk5hYI.mjs → placeholder-Ci0RLeCk.mjs} +1 -1
- package/dist/{placeholder-C-fk5hYI.mjs.map → placeholder-Ci0RLeCk.mjs.map} +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.mjs +6 -5
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
- package/dist/public-url-B1AxbbbQ.mjs +51 -0
- package/dist/public-url-B1AxbbbQ.mjs.map +1 -0
- package/dist/{query-fqEdLFms.mjs → query-Bo-msrmu.mjs} +114 -16
- package/dist/query-Bo-msrmu.mjs.map +1 -0
- package/dist/{redirect-D_pshWdf.mjs → redirect-C5H7VGIX.mjs} +11 -6
- package/dist/redirect-C5H7VGIX.mjs.map +1 -0
- package/dist/{registry-C3Mr0ODu.mjs → registry-Beb7wxFc.mjs} +39 -5
- package/dist/registry-Beb7wxFc.mjs.map +1 -0
- package/dist/{request-cache-Ci7f5pBb.mjs → request-cache-C-tIpYIw.mjs} +1 -1
- package/dist/{request-cache-Ci7f5pBb.mjs.map → request-cache-C-tIpYIw.mjs.map} +1 -1
- package/dist/runner-Clwe4Mme.d.mts +44 -0
- package/dist/runner-Clwe4Mme.d.mts.map +1 -0
- package/dist/{runner-tQ7BJ4T7.mjs → runner-DMnlIkh4.mjs} +616 -191
- package/dist/runner-DMnlIkh4.mjs.map +1 -0
- package/dist/runtime.d.mts +6 -6
- package/dist/runtime.mjs +2 -2
- package/dist/{search-BoZYFuUk.mjs → search-DkN-BqsS.mjs} +270 -152
- package/dist/search-DkN-BqsS.mjs.map +1 -0
- package/dist/secrets-CZ8rxLX3.mjs +314 -0
- package/dist/secrets-CZ8rxLX3.mjs.map +1 -0
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +13 -11
- package/dist/seo/index.d.mts +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/taxonomies-CTtewrSQ.mjs +407 -0
- package/dist/taxonomies-CTtewrSQ.mjs.map +1 -0
- package/dist/taxonomy-DSxx2K2L.mjs +218 -0
- package/dist/taxonomy-DSxx2K2L.mjs.map +1 -0
- package/dist/{tokens-D9vnZqYS.mjs → tokens-CyRDPVW2.mjs} +1 -1
- package/dist/{tokens-D9vnZqYS.mjs.map → tokens-CyRDPVW2.mjs.map} +1 -1
- package/dist/{transaction-Cn2rjY78.mjs → transaction-D44LBXvU.mjs} +1 -1
- package/dist/{transaction-Cn2rjY78.mjs.map → transaction-D44LBXvU.mjs.map} +1 -1
- package/dist/{transport-CUnEL3Vs.d.mts → transport-DX_5rpsq.d.mts} +1 -1
- package/dist/{transport-CUnEL3Vs.d.mts.map → transport-DX_5rpsq.d.mts.map} +1 -1
- package/dist/{transport-C9ugt2Nr.mjs → transport-xpzIjCIB.mjs} +6 -5
- package/dist/{transport-C9ugt2Nr.mjs.map → transport-xpzIjCIB.mjs.map} +1 -1
- package/dist/{types-BrA0xf5I.d.mts → types-B_CXXnzh.d.mts} +1 -1
- package/dist/{types-BrA0xf5I.d.mts.map → types-B_CXXnzh.d.mts.map} +1 -1
- package/dist/{types-DIMwPFub.d.mts → types-C-aFbqmA.d.mts} +1 -1
- package/dist/{types-DIMwPFub.d.mts.map → types-C-aFbqmA.d.mts.map} +1 -1
- package/dist/types-CoO6mpV3.mjs +68 -0
- package/dist/types-CoO6mpV3.mjs.map +1 -0
- package/dist/{types-i36XcA_X.d.mts → types-D19uBYWn.d.mts} +83 -7
- package/dist/types-D19uBYWn.d.mts.map +1 -0
- package/dist/{types-BmPPSUEx.d.mts → types-Dl1fgFjn.d.mts} +24 -2
- package/dist/{types-BmPPSUEx.d.mts.map → types-Dl1fgFjn.d.mts.map} +1 -1
- package/dist/{types-CS8FIX7L.d.mts → types-Dtx1mSMX.d.mts} +9 -1
- package/dist/types-Dtx1mSMX.d.mts.map +1 -0
- package/dist/{types-Bm1dn-q3.mjs → types-Eg829jj9.mjs} +1 -1
- package/dist/{types-Bm1dn-q3.mjs.map → types-Eg829jj9.mjs.map} +1 -1
- package/dist/{types-CgqmmMJB.mjs → types-K-EkEQCI.mjs} +1 -1
- package/dist/{types-CgqmmMJB.mjs.map → types-K-EkEQCI.mjs.map} +1 -1
- package/dist/{validate-CxVsLehf.mjs → validate-CBIbxM3L.mjs} +14 -10
- package/dist/validate-CBIbxM3L.mjs.map +1 -0
- package/dist/{validate-DHxmpFJt.d.mts → validate-DHGwADqO.d.mts} +18 -5
- package/dist/validate-DHGwADqO.d.mts.map +1 -0
- package/dist/{validation-C-ZpN2GI.mjs → validation-B1NYiEos.mjs} +6 -6
- package/dist/{validation-C-ZpN2GI.mjs.map → validation-B1NYiEos.mjs.map} +1 -1
- package/dist/version-CMD42IRC.mjs +7 -0
- package/dist/{version-Bbq8TCrz.mjs.map → version-CMD42IRC.mjs.map} +1 -1
- package/dist/{zod-generator-CpwccCIv.mjs → zod-generator-BNJDQBSZ.mjs} +11 -6
- package/dist/{zod-generator-CpwccCIv.mjs.map → zod-generator-BNJDQBSZ.mjs.map} +1 -1
- package/locals.d.ts +1 -6
- package/package.json +9 -8
- package/src/api/handlers/comments.ts +6 -4
- package/src/api/handlers/content.ts +40 -1
- package/src/api/handlers/dashboard.ts +29 -36
- package/src/api/handlers/device-flow.ts +5 -0
- package/src/api/handlers/marketplace.ts +11 -4
- package/src/api/handlers/menus.ts +256 -75
- package/src/api/handlers/oauth-authorization.ts +72 -33
- package/src/api/handlers/revision.ts +23 -14
- package/src/api/handlers/taxonomies.ts +273 -100
- package/src/api/public-url.ts +48 -2
- package/src/api/schemas/comments.ts +2 -2
- package/src/api/schemas/common.ts +7 -0
- package/src/api/schemas/content.ts +17 -0
- package/src/api/schemas/menus.ts +23 -0
- package/src/api/schemas/sections.ts +3 -3
- package/src/api/schemas/taxonomies.ts +39 -0
- package/src/api/schemas/users.ts +1 -1
- package/src/api/types.ts +5 -1
- package/src/astro/integration/index.ts +17 -0
- package/src/astro/integration/routes.ts +10 -0
- package/src/astro/integration/runtime.ts +30 -0
- package/src/astro/integration/virtual-modules.ts +32 -2
- package/src/astro/integration/vite-config.ts +6 -1
- package/src/astro/middleware/auth.ts +13 -6
- package/src/astro/middleware/redirect.ts +29 -16
- package/src/astro/middleware/request-context.ts +15 -5
- package/src/astro/middleware.ts +23 -9
- package/src/astro/routes/api/auth/invite/complete.ts +6 -1
- package/src/astro/routes/api/auth/passkey/register/verify.ts +6 -1
- package/src/astro/routes/api/auth/passkey/verify.ts +6 -1
- package/src/astro/routes/api/auth/signup/complete.ts +6 -1
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +4 -2
- package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +1 -1
- package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +34 -12
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +32 -2
- package/src/astro/routes/api/content/[collection]/[id]/restore.ts +4 -2
- package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +3 -2
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +8 -4
- package/src/astro/routes/api/content/[collection]/[id].ts +12 -0
- package/src/astro/routes/api/import/wordpress/execute.ts +3 -1
- package/src/astro/routes/api/import/wordpress/prepare.ts +7 -8
- package/src/astro/routes/api/import/wordpress/rewrite-url-helpers.ts +196 -0
- package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +9 -177
- package/src/astro/routes/api/import/wordpress-plugin/execute.ts +3 -1
- package/src/astro/routes/api/manifest.ts +62 -45
- package/src/astro/routes/api/media/[id]/confirm.ts +10 -1
- package/src/astro/routes/api/media/providers/[providerId]/index.ts +12 -3
- package/src/astro/routes/api/menus/[name]/items.ts +16 -6
- package/src/astro/routes/api/menus/[name]/reorder.ts +8 -3
- package/src/astro/routes/api/menus/[name]/translations.ts +82 -0
- package/src/astro/routes/api/menus/[name].ts +19 -10
- package/src/astro/routes/api/menus/index.ts +9 -6
- package/src/astro/routes/api/openapi.json.ts +27 -10
- package/src/astro/routes/api/redirects/404s/index.ts +10 -4
- package/src/astro/routes/api/redirects/404s/summary.ts +4 -2
- package/src/astro/routes/api/redirects/[id].ts +10 -4
- package/src/astro/routes/api/redirects/index.ts +7 -3
- package/src/astro/routes/api/revisions/[revisionId]/index.ts +1 -1
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +0 -2
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +0 -1
- package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +0 -1
- package/src/astro/routes/api/schema/collections/[slug]/index.ts +2 -2
- package/src/astro/routes/api/schema/collections/index.ts +1 -1
- package/src/astro/routes/api/search/index.ts +10 -2
- package/src/astro/routes/api/sections/[slug].ts +10 -4
- package/src/astro/routes/api/sections/index.ts +7 -3
- package/src/astro/routes/api/setup/admin-verify.ts +6 -1
- package/src/astro/routes/api/snapshot.ts +44 -18
- package/src/astro/routes/api/taxonomies/[name]/terms/[slug]/translations.ts +89 -0
- package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +22 -22
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +11 -14
- package/src/astro/routes/api/taxonomies/index.ts +9 -7
- package/src/astro/routes/api/themes/preview.ts +11 -5
- package/src/astro/types.ts +23 -3
- package/src/auth/allowed-origins.ts +168 -0
- package/src/auth/passkey-config.ts +35 -13
- package/src/bylines/index.ts +37 -88
- package/src/cli/commands/auth.ts +28 -6
- package/src/cli/commands/bundle-utils.ts +11 -2
- package/src/cli/commands/bundle.ts +28 -8
- package/src/cli/commands/content.ts +13 -0
- package/src/cli/commands/export-seed.ts +82 -21
- package/src/cli/commands/login.ts +8 -1
- package/src/cli/commands/plugin-init.ts +216 -90
- package/src/cli/commands/publish.ts +24 -0
- package/src/cli/commands/secrets.ts +183 -0
- package/src/cli/credentials.ts +1 -1
- package/src/cli/index.ts +5 -1
- package/src/client/index.ts +4 -4
- package/src/client/transport.ts +17 -7
- package/src/components/Break.astro +2 -2
- package/src/components/EmDashHead.astro +18 -13
- package/src/components/Embed.astro +1 -1
- package/src/components/Gallery.astro +1 -1
- package/src/components/Image.astro +1 -1
- package/src/components/InlinePortableTextEditor.tsx +104 -18
- package/src/config/secrets.ts +528 -0
- package/src/database/dialect-helpers.ts +50 -0
- package/src/database/migrations/034_published_at_index.ts +1 -1
- package/src/database/migrations/035_bounded_404_log.ts +56 -39
- package/src/database/migrations/036_i18n_menus_and_taxonomies.ts +477 -0
- package/src/database/migrations/runner.ts +158 -23
- package/src/database/repositories/content.ts +47 -12
- package/src/database/repositories/redirect.ts +14 -3
- package/src/database/repositories/taxonomy.ts +212 -82
- package/src/database/types.ts +10 -2
- package/src/db/libsql.ts +1 -3
- package/src/db/sqlite.ts +2 -5
- package/src/emdash-runtime.ts +84 -159
- package/src/i18n/resolve.ts +37 -0
- package/src/index.ts +9 -0
- package/src/loader.ts +73 -3
- package/src/mcp/server.ts +180 -54
- package/src/menus/index.ts +143 -124
- package/src/menus/types.ts +15 -1
- package/src/page/site-identity.ts +58 -0
- package/src/plugins/adapt-sandbox-entry.ts +22 -10
- package/src/plugins/context.ts +13 -10
- package/src/plugins/define-plugin.ts +40 -12
- package/src/plugins/hooks.ts +23 -19
- package/src/plugins/index.ts +9 -0
- package/src/plugins/manifest-schema.ts +37 -2
- package/src/plugins/types.ts +151 -11
- package/src/preview/urls.ts +23 -3
- package/src/query.ts +148 -5
- package/src/redirects/cache.ts +38 -18
- package/src/schema/registry.ts +56 -0
- package/src/schema/zod-generator.ts +39 -7
- package/src/seed/apply.ts +142 -54
- package/src/seed/types.ts +14 -1
- package/src/seed/validate.ts +27 -13
- package/src/settings/index.ts +80 -6
- package/src/settings/types.ts +23 -1
- package/src/taxonomies/index.ts +237 -210
- package/src/taxonomies/types.ts +10 -0
- package/dist/apply-x0eMK1lX.mjs.map +0 -1
- package/dist/bylines-CRNsVG88.mjs +0 -157
- package/dist/bylines-CRNsVG88.mjs.map +0 -1
- package/dist/cache-BkKBuIvS.mjs +0 -56
- package/dist/cache-BkKBuIvS.mjs.map +0 -1
- package/dist/chunk-ClPoSABd.mjs +0 -21
- package/dist/content-BcQPYxdV.mjs.map +0 -1
- package/dist/dialect-helpers-DhTzaUxP.mjs.map +0 -1
- package/dist/index-DIb-CzNx.d.mts.map +0 -1
- package/dist/loader-CndGj8kM.mjs.map +0 -1
- package/dist/manifest-schema-DH9xhc6t.mjs.map +0 -1
- package/dist/query-fqEdLFms.mjs.map +0 -1
- package/dist/redirect-D_pshWdf.mjs.map +0 -1
- package/dist/registry-C3Mr0ODu.mjs.map +0 -1
- package/dist/runner-OURCaApa.d.mts +0 -34
- package/dist/runner-OURCaApa.d.mts.map +0 -1
- package/dist/runner-tQ7BJ4T7.mjs.map +0 -1
- package/dist/search-BoZYFuUk.mjs.map +0 -1
- package/dist/taxonomies-B4IAshV8.mjs +0 -308
- package/dist/taxonomies-B4IAshV8.mjs.map +0 -1
- package/dist/types-CS8FIX7L.d.mts.map +0 -1
- package/dist/types-i36XcA_X.d.mts.map +0 -1
- package/dist/validate-CxVsLehf.mjs.map +0 -1
- package/dist/validate-DHxmpFJt.d.mts.map +0 -1
- package/dist/version-Bbq8TCrz.mjs +0 -7
package/src/mcp/server.ts
CHANGED
|
@@ -14,6 +14,8 @@ import { canActOnOwn, hasPermission, Role } from "@emdash-cms/auth";
|
|
|
14
14
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
|
|
17
|
+
import { contentBylineInputSchema, contentSeoInput } from "#api/schemas.js";
|
|
18
|
+
|
|
17
19
|
import type { EmDashHandlers } from "../astro/types.js";
|
|
18
20
|
import { hasScope } from "../auth/api-tokens.js";
|
|
19
21
|
|
|
@@ -623,7 +625,10 @@ export function createMcpServer(): McpServer {
|
|
|
623
625
|
"Update an existing content item. Only include fields you want to change " +
|
|
624
626
|
"in the 'data' object — unspecified fields are left unchanged. Pass the " +
|
|
625
627
|
"_rev token from content_get to enable optimistic concurrency checking " +
|
|
626
|
-
"(the update fails if the item was modified since you read it)."
|
|
628
|
+
"(the update fails if the item was modified since you read it). " +
|
|
629
|
+
"`seo` and `bylines` are persisted alongside the field updates in a " +
|
|
630
|
+
"single transaction. `publishedAt` requires the content:publish_any " +
|
|
631
|
+
"permission and is useful for migrations or correcting historical dates.",
|
|
627
632
|
inputSchema: z.object({
|
|
628
633
|
collection: z.string().describe("Collection slug"),
|
|
629
634
|
id: z.string().describe("Content item ID or slug"),
|
|
@@ -638,6 +643,28 @@ export function createMcpServer(): McpServer {
|
|
|
638
643
|
.describe(
|
|
639
644
|
"New status. Setting to 'published' requires publish permission. Setting to 'draft' unpublishes the item and also requires publish permission.",
|
|
640
645
|
),
|
|
646
|
+
// Reuse the REST schema rather than redefining inline. The REST schema's
|
|
647
|
+
// `canonical` field is gated through `httpUrl` (validates the URL parses
|
|
648
|
+
// AND has an http(s) scheme) which rejects javascript:/data: URIs that
|
|
649
|
+
// would otherwise become stored XSS in the rendered <link rel="canonical">.
|
|
650
|
+
// Inlining a looser shape here would let MCP callers bypass that.
|
|
651
|
+
seo: contentSeoInput
|
|
652
|
+
.optional()
|
|
653
|
+
.describe(
|
|
654
|
+
"Per-content SEO metadata. Only valid for collections with SEO enabled (see schema_get_collection.hasSeo). Fields not included are left unchanged; pass null to clear.",
|
|
655
|
+
),
|
|
656
|
+
bylines: z
|
|
657
|
+
.array(contentBylineInputSchema)
|
|
658
|
+
.optional()
|
|
659
|
+
.describe(
|
|
660
|
+
"Replace the byline list for this item. The first entry becomes the primary byline. Pass an empty array to clear all bylines.",
|
|
661
|
+
),
|
|
662
|
+
publishedAt: z.iso
|
|
663
|
+
.datetime({ offset: true, message: "must be an ISO 8601 datetime" })
|
|
664
|
+
.nullish()
|
|
665
|
+
.describe(
|
|
666
|
+
"Override the publication timestamp (ISO 8601). Requires content:publish_any permission. Pass null to clear. Useful for content migrations.",
|
|
667
|
+
),
|
|
641
668
|
_rev: z
|
|
642
669
|
.string()
|
|
643
670
|
.optional()
|
|
@@ -647,35 +674,48 @@ export function createMcpServer(): McpServer {
|
|
|
647
674
|
async (args, extra) => {
|
|
648
675
|
requireScope(extra, "content:write");
|
|
649
676
|
requireRole(extra, Role.AUTHOR);
|
|
650
|
-
const { emdash, userId } = getExtra(extra);
|
|
677
|
+
const { emdash, userId, userRole } = getExtra(extra);
|
|
651
678
|
|
|
652
679
|
// Fetch item to check ownership
|
|
653
680
|
const existing = await emdash.handleContentGet(args.collection, args.id);
|
|
654
681
|
if (!existing.success) {
|
|
655
682
|
return unwrap(existing);
|
|
656
683
|
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
684
|
+
const ownerId = extractContentAuthorId(existing.data);
|
|
685
|
+
requireOwnership(extra, ownerId, "content:edit_own", "content:edit_any");
|
|
686
|
+
|
|
687
|
+
// Writing publishedAt directly (incl. clearing to null) overwrites
|
|
688
|
+
// historical record — gate behind publish_any, mirroring the REST PUT
|
|
689
|
+
// route. Status-driven publishes are gated separately below.
|
|
690
|
+
if (args.publishedAt !== undefined) {
|
|
691
|
+
const user = { id: userId, role: userRole };
|
|
692
|
+
if (!hasPermission(user, "content:publish_any" as Permission)) {
|
|
693
|
+
throw new EmDashAuthError(
|
|
694
|
+
"Setting publishedAt requires content:publish_any permission",
|
|
695
|
+
"INSUFFICIENT_PERMISSIONS",
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
663
699
|
|
|
664
700
|
const resolvedId = extractContentId(existing.data) ?? args.id;
|
|
665
701
|
|
|
666
702
|
// Status transitions route through dedicated handlers for proper revision management
|
|
667
703
|
if (args.status === "published") {
|
|
668
|
-
requireOwnership(
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
704
|
+
requireOwnership(extra, ownerId, "content:publish_own", "content:publish_any");
|
|
705
|
+
if (
|
|
706
|
+
args.data ||
|
|
707
|
+
args.slug ||
|
|
708
|
+
args.seo !== undefined ||
|
|
709
|
+
args.bylines !== undefined ||
|
|
710
|
+
args.publishedAt !== undefined
|
|
711
|
+
) {
|
|
675
712
|
const updateResult = await emdash.handleContentUpdate(args.collection, resolvedId, {
|
|
676
713
|
data: args.data,
|
|
677
714
|
slug: args.slug,
|
|
678
715
|
authorId: userId,
|
|
716
|
+
seo: args.seo,
|
|
717
|
+
bylines: args.bylines,
|
|
718
|
+
publishedAt: args.publishedAt,
|
|
679
719
|
_rev: args._rev,
|
|
680
720
|
});
|
|
681
721
|
if (!updateResult.success) return unwrap(updateResult);
|
|
@@ -684,17 +724,21 @@ export function createMcpServer(): McpServer {
|
|
|
684
724
|
}
|
|
685
725
|
|
|
686
726
|
if (args.status === "draft") {
|
|
687
|
-
requireOwnership(
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
727
|
+
requireOwnership(extra, ownerId, "content:publish_own", "content:publish_any");
|
|
728
|
+
if (
|
|
729
|
+
args.data ||
|
|
730
|
+
args.slug ||
|
|
731
|
+
args.seo !== undefined ||
|
|
732
|
+
args.bylines !== undefined ||
|
|
733
|
+
args.publishedAt !== undefined
|
|
734
|
+
) {
|
|
694
735
|
const updateResult = await emdash.handleContentUpdate(args.collection, resolvedId, {
|
|
695
736
|
data: args.data,
|
|
696
737
|
slug: args.slug,
|
|
697
738
|
authorId: userId,
|
|
739
|
+
seo: args.seo,
|
|
740
|
+
bylines: args.bylines,
|
|
741
|
+
publishedAt: args.publishedAt,
|
|
698
742
|
_rev: args._rev,
|
|
699
743
|
});
|
|
700
744
|
if (!updateResult.success) return unwrap(updateResult);
|
|
@@ -707,6 +751,9 @@ export function createMcpServer(): McpServer {
|
|
|
707
751
|
data: args.data,
|
|
708
752
|
slug: args.slug,
|
|
709
753
|
authorId: userId,
|
|
754
|
+
seo: args.seo,
|
|
755
|
+
bylines: args.bylines,
|
|
756
|
+
publishedAt: args.publishedAt,
|
|
710
757
|
_rev: args._rev,
|
|
711
758
|
}),
|
|
712
759
|
);
|
|
@@ -809,31 +856,53 @@ export function createMcpServer(): McpServer {
|
|
|
809
856
|
description:
|
|
810
857
|
"Publish a content item, making it live on the site. Creates a published " +
|
|
811
858
|
"revision from the current draft. Further edits create a new draft without " +
|
|
812
|
-
"affecting the live version until re-published."
|
|
859
|
+
"affecting the live version until re-published. Pass `publishedAt` to " +
|
|
860
|
+
"backdate (e.g. when migrating content from another CMS) — this requires " +
|
|
861
|
+
"the content:publish_any permission. Without `publishedAt`, the existing " +
|
|
862
|
+
"`published_at` is preserved on re-publish (idempotent) and falls back to " +
|
|
863
|
+
"the current time on first publish.",
|
|
813
864
|
inputSchema: z.object({
|
|
814
865
|
collection: z.string().describe("Collection slug"),
|
|
815
866
|
id: z.string().describe("Content item ID or slug"),
|
|
867
|
+
publishedAt: z.iso
|
|
868
|
+
.datetime({ offset: true, message: "must be an ISO 8601 datetime" })
|
|
869
|
+
.optional()
|
|
870
|
+
.describe(
|
|
871
|
+
"Override publication timestamp (ISO 8601). Requires content:publish_any permission. Useful when importing content with original publish dates.",
|
|
872
|
+
),
|
|
816
873
|
}),
|
|
817
874
|
},
|
|
818
875
|
async (args, extra) => {
|
|
819
876
|
requireScope(extra, "content:write");
|
|
820
877
|
requireRole(extra, Role.AUTHOR);
|
|
821
|
-
const
|
|
878
|
+
const { emdash, userId, userRole } = getExtra(extra);
|
|
822
879
|
|
|
823
880
|
// Fetch item to check ownership
|
|
824
|
-
const existing = await
|
|
881
|
+
const existing = await emdash.handleContentGet(args.collection, args.id);
|
|
825
882
|
if (!existing.success) {
|
|
826
883
|
return unwrap(existing);
|
|
827
884
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
)
|
|
885
|
+
const ownerId = extractContentAuthorId(existing.data);
|
|
886
|
+
requireOwnership(extra, ownerId, "content:publish_own", "content:publish_any");
|
|
887
|
+
|
|
888
|
+
// Backdating overwrites historical record — gate behind publish_any
|
|
889
|
+
// regardless of ownership (mirrors the REST PUT route's publishedAt gate).
|
|
890
|
+
if (args.publishedAt !== undefined) {
|
|
891
|
+
const user = { id: userId, role: userRole };
|
|
892
|
+
if (!hasPermission(user, "content:publish_any" as Permission)) {
|
|
893
|
+
throw new EmDashAuthError(
|
|
894
|
+
"Setting publishedAt requires content:publish_any permission",
|
|
895
|
+
"INSUFFICIENT_PERMISSIONS",
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
834
899
|
|
|
835
900
|
const resolvedId = extractContentId(existing.data) ?? args.id;
|
|
836
|
-
return unwrap(
|
|
901
|
+
return unwrap(
|
|
902
|
+
await emdash.handleContentPublish(args.collection, resolvedId, {
|
|
903
|
+
publishedAt: args.publishedAt,
|
|
904
|
+
}),
|
|
905
|
+
);
|
|
837
906
|
},
|
|
838
907
|
);
|
|
839
908
|
|
|
@@ -1195,7 +1264,7 @@ export function createMcpServer(): McpServer {
|
|
|
1195
1264
|
// ['drafts', 'revisions'] when undefined; pass through verbatim.
|
|
1196
1265
|
supports: args.supports,
|
|
1197
1266
|
});
|
|
1198
|
-
ec.
|
|
1267
|
+
ec.invalidateUrlPatternCache();
|
|
1199
1268
|
return jsonResult(collection);
|
|
1200
1269
|
} catch (error) {
|
|
1201
1270
|
return respondHandlerError(error, "SCHEMA_CREATE_ERROR");
|
|
@@ -1227,7 +1296,7 @@ export function createMcpServer(): McpServer {
|
|
|
1227
1296
|
const { SchemaRegistry } = await import("../schema/index.js");
|
|
1228
1297
|
const registry = new SchemaRegistry(ec.db);
|
|
1229
1298
|
await registry.deleteCollection(args.slug, { force: args.force });
|
|
1230
|
-
ec.
|
|
1299
|
+
ec.invalidateUrlPatternCache();
|
|
1231
1300
|
return jsonResult({ deleted: args.slug });
|
|
1232
1301
|
} catch (error) {
|
|
1233
1302
|
return respondHandlerError(error, "SCHEMA_DELETE_ERROR");
|
|
@@ -1331,7 +1400,6 @@ export function createMcpServer(): McpServer {
|
|
|
1331
1400
|
searchable: args.searchable,
|
|
1332
1401
|
translatable: args.translatable,
|
|
1333
1402
|
});
|
|
1334
|
-
ec.invalidateManifest();
|
|
1335
1403
|
return jsonResult(field);
|
|
1336
1404
|
} catch (error) {
|
|
1337
1405
|
return respondHandlerError(error, "FIELD_CREATE_ERROR");
|
|
@@ -1360,7 +1428,6 @@ export function createMcpServer(): McpServer {
|
|
|
1360
1428
|
const { SchemaRegistry } = await import("../schema/index.js");
|
|
1361
1429
|
const registry = new SchemaRegistry(ec.db);
|
|
1362
1430
|
await registry.deleteField(args.collection, args.fieldSlug);
|
|
1363
|
-
ec.invalidateManifest();
|
|
1364
1431
|
return jsonResult({ deleted: args.fieldSlug, collection: args.collection });
|
|
1365
1432
|
} catch (error) {
|
|
1366
1433
|
return respondHandlerError(error, "FIELD_DELETE_ERROR");
|
|
@@ -1600,16 +1667,19 @@ export function createMcpServer(): McpServer {
|
|
|
1600
1667
|
description:
|
|
1601
1668
|
"List all taxonomy definitions (e.g. categories, tags). Taxonomies are " +
|
|
1602
1669
|
"classification systems applied to content. Each has a name, label, and " +
|
|
1603
|
-
"can be hierarchical (categories) or flat (tags)."
|
|
1604
|
-
|
|
1670
|
+
"can be hierarchical (categories) or flat (tags). Optionally filter by " +
|
|
1671
|
+
"locale.",
|
|
1672
|
+
inputSchema: z.object({
|
|
1673
|
+
locale: z.string().optional().describe("Filter by locale (omit for all)"),
|
|
1674
|
+
}),
|
|
1605
1675
|
annotations: { readOnlyHint: true },
|
|
1606
1676
|
},
|
|
1607
|
-
async (
|
|
1677
|
+
async (args, extra) => {
|
|
1608
1678
|
requireScope(extra, "content:read");
|
|
1609
1679
|
const ec = getEmDash(extra);
|
|
1610
1680
|
try {
|
|
1611
1681
|
const { handleTaxonomyList } = await import("../api/handlers/taxonomies.js");
|
|
1612
|
-
return unwrap(await handleTaxonomyList(ec.db));
|
|
1682
|
+
return unwrap(await handleTaxonomyList(ec.db, { locale: args.locale }));
|
|
1613
1683
|
} catch (error) {
|
|
1614
1684
|
return respondHandlerError(error, "TAXONOMY_LIST_ERROR");
|
|
1615
1685
|
}
|
|
@@ -1628,6 +1698,7 @@ export function createMcpServer(): McpServer {
|
|
|
1628
1698
|
taxonomy: z.string().describe("Taxonomy name (e.g. 'categories', 'tags')"),
|
|
1629
1699
|
limit: z.number().int().min(1).max(100).optional().describe("Max items (default 50)"),
|
|
1630
1700
|
cursor: z.string().min(1).max(2048).optional().describe("Pagination cursor"),
|
|
1701
|
+
locale: z.string().optional().describe("Filter by locale (omit for all)"),
|
|
1631
1702
|
}),
|
|
1632
1703
|
annotations: { readOnlyHint: true },
|
|
1633
1704
|
},
|
|
@@ -1635,9 +1706,8 @@ export function createMcpServer(): McpServer {
|
|
|
1635
1706
|
requireScope(extra, "content:read");
|
|
1636
1707
|
const ec = getEmDash(extra);
|
|
1637
1708
|
try {
|
|
1638
|
-
// Verify taxonomy exists via handler layer
|
|
1639
1709
|
const { handleTaxonomyList } = await import("../api/handlers/taxonomies.js");
|
|
1640
|
-
const listResult = await handleTaxonomyList(ec.db);
|
|
1710
|
+
const listResult = await handleTaxonomyList(ec.db, { locale: args.locale });
|
|
1641
1711
|
if (!listResult.success) return unwrap(listResult);
|
|
1642
1712
|
|
|
1643
1713
|
const taxonomies = (listResult.data as { taxonomies: Array<{ name: string; id?: string }> })
|
|
@@ -1645,13 +1715,12 @@ export function createMcpServer(): McpServer {
|
|
|
1645
1715
|
const taxonomy = taxonomies.find((t: { name: string }) => t.name === args.taxonomy);
|
|
1646
1716
|
if (!taxonomy) return respondError("NOT_FOUND", `Taxonomy '${args.taxonomy}' not found`);
|
|
1647
1717
|
|
|
1648
|
-
// Paginated term query via repository (avoids N+1 of handleTermList)
|
|
1649
1718
|
const { TaxonomyRepository } = await import("../database/repositories/taxonomy.js");
|
|
1650
1719
|
const { decodeCursor, encodeCursor, InvalidCursorError } =
|
|
1651
1720
|
await import("../database/repositories/types.js");
|
|
1652
1721
|
const repo = new TaxonomyRepository(ec.db);
|
|
1653
1722
|
const limit = Math.min(args.limit ?? 50, 100);
|
|
1654
|
-
const terms = await repo.findByName(args.taxonomy);
|
|
1723
|
+
const terms = await repo.findByName(args.taxonomy, { locale: args.locale });
|
|
1655
1724
|
|
|
1656
1725
|
// Manual keyset pagination over the sorted-by-label results.
|
|
1657
1726
|
// Using a base64-encoded `(label, id)` cursor matches the
|
|
@@ -1693,6 +1762,8 @@ export function createMcpServer(): McpServer {
|
|
|
1693
1762
|
label: t.label,
|
|
1694
1763
|
parentId: t.parentId,
|
|
1695
1764
|
description: typeof t.data?.description === "string" ? t.data.description : undefined,
|
|
1765
|
+
locale: t.locale,
|
|
1766
|
+
translationGroup: t.translationGroup,
|
|
1696
1767
|
})),
|
|
1697
1768
|
nextCursor,
|
|
1698
1769
|
});
|
|
@@ -1718,6 +1789,11 @@ export function createMcpServer(): McpServer {
|
|
|
1718
1789
|
label: z.string().describe("Display name"),
|
|
1719
1790
|
parentId: z.string().optional().describe("Parent term ID for hierarchical taxonomies"),
|
|
1720
1791
|
description: z.string().optional().describe("Description of the term"),
|
|
1792
|
+
locale: z.string().optional().describe("Locale for the new term (e.g. 'es')"),
|
|
1793
|
+
translationOf: z
|
|
1794
|
+
.string()
|
|
1795
|
+
.optional()
|
|
1796
|
+
.describe("Term id to join as a translation (same translation_group)"),
|
|
1721
1797
|
}),
|
|
1722
1798
|
},
|
|
1723
1799
|
async (args, extra) => {
|
|
@@ -1732,6 +1808,8 @@ export function createMcpServer(): McpServer {
|
|
|
1732
1808
|
label: args.label,
|
|
1733
1809
|
parentId: args.parentId,
|
|
1734
1810
|
description: args.description,
|
|
1811
|
+
locale: args.locale,
|
|
1812
|
+
translationOf: args.translationOf,
|
|
1735
1813
|
}),
|
|
1736
1814
|
);
|
|
1737
1815
|
} catch (error) {
|
|
@@ -1808,6 +1886,29 @@ export function createMcpServer(): McpServer {
|
|
|
1808
1886
|
},
|
|
1809
1887
|
);
|
|
1810
1888
|
|
|
1889
|
+
server.registerTool(
|
|
1890
|
+
"taxonomy_term_translations",
|
|
1891
|
+
{
|
|
1892
|
+
title: "List Term Translations",
|
|
1893
|
+
description:
|
|
1894
|
+
"Return every locale variant of a taxonomy term, identified via its shared translation_group.",
|
|
1895
|
+
inputSchema: z.object({
|
|
1896
|
+
id: z.string().describe("Term id (or translation_group)"),
|
|
1897
|
+
}),
|
|
1898
|
+
annotations: { readOnlyHint: true },
|
|
1899
|
+
},
|
|
1900
|
+
async (args, extra) => {
|
|
1901
|
+
requireScope(extra, "content:read");
|
|
1902
|
+
const ec = getEmDash(extra);
|
|
1903
|
+
try {
|
|
1904
|
+
const { handleTermTranslations } = await import("../api/handlers/taxonomies.js");
|
|
1905
|
+
return unwrap(await handleTermTranslations(ec.db, args.id));
|
|
1906
|
+
} catch (error) {
|
|
1907
|
+
return respondHandlerError(error, "TERM_TRANSLATIONS_ERROR");
|
|
1908
|
+
}
|
|
1909
|
+
},
|
|
1910
|
+
);
|
|
1911
|
+
|
|
1811
1912
|
// =====================================================================
|
|
1812
1913
|
// Menu tools
|
|
1813
1914
|
// =====================================================================
|
|
@@ -1817,18 +1918,20 @@ export function createMcpServer(): McpServer {
|
|
|
1817
1918
|
{
|
|
1818
1919
|
title: "List Menus",
|
|
1819
1920
|
description:
|
|
1820
|
-
"List
|
|
1821
|
-
"
|
|
1822
|
-
"
|
|
1823
|
-
inputSchema: z.object({
|
|
1921
|
+
"List navigation menus. Menus are per-locale: filter by `locale` to " +
|
|
1922
|
+
"get just one locale's worth, or omit to list every row (one per " +
|
|
1923
|
+
"locale per menu name).",
|
|
1924
|
+
inputSchema: z.object({
|
|
1925
|
+
locale: z.string().optional().describe("Filter by locale (omit for all)"),
|
|
1926
|
+
}),
|
|
1824
1927
|
annotations: { readOnlyHint: true },
|
|
1825
1928
|
},
|
|
1826
|
-
async (
|
|
1929
|
+
async (args, extra) => {
|
|
1827
1930
|
requireScope(extra, "content:read");
|
|
1828
1931
|
const ec = getEmDash(extra);
|
|
1829
1932
|
try {
|
|
1830
1933
|
const { handleMenuList } = await import("../api/handlers/menus.js");
|
|
1831
|
-
return unwrap(await handleMenuList(ec.db));
|
|
1934
|
+
return unwrap(await handleMenuList(ec.db, { locale: args.locale }));
|
|
1832
1935
|
} catch (error) {
|
|
1833
1936
|
return respondHandlerError(error, "MENU_LIST_ERROR");
|
|
1834
1937
|
}
|
|
@@ -1840,11 +1943,11 @@ export function createMcpServer(): McpServer {
|
|
|
1840
1943
|
{
|
|
1841
1944
|
title: "Get Menu with Items",
|
|
1842
1945
|
description:
|
|
1843
|
-
"Get a menu by name including
|
|
1844
|
-
"
|
|
1845
|
-
"for nesting.",
|
|
1946
|
+
"Get a menu by name, including its items. When multiple locales exist, " +
|
|
1947
|
+
"pass `locale` to pick the right one.",
|
|
1846
1948
|
inputSchema: z.object({
|
|
1847
1949
|
name: z.string().describe("Menu name (e.g. 'main', 'footer')"),
|
|
1950
|
+
locale: z.string().optional().describe("Locale to resolve the menu for"),
|
|
1848
1951
|
}),
|
|
1849
1952
|
annotations: { readOnlyHint: true },
|
|
1850
1953
|
},
|
|
@@ -1853,13 +1956,36 @@ export function createMcpServer(): McpServer {
|
|
|
1853
1956
|
const ec = getEmDash(extra);
|
|
1854
1957
|
try {
|
|
1855
1958
|
const { handleMenuGet } = await import("../api/handlers/menus.js");
|
|
1856
|
-
return unwrap(await handleMenuGet(ec.db, args.name));
|
|
1959
|
+
return unwrap(await handleMenuGet(ec.db, args.name, { locale: args.locale }));
|
|
1857
1960
|
} catch (error) {
|
|
1858
1961
|
return respondHandlerError(error, "MENU_GET_ERROR");
|
|
1859
1962
|
}
|
|
1860
1963
|
},
|
|
1861
1964
|
);
|
|
1862
1965
|
|
|
1966
|
+
server.registerTool(
|
|
1967
|
+
"menu_translations",
|
|
1968
|
+
{
|
|
1969
|
+
title: "List Menu Translations",
|
|
1970
|
+
description:
|
|
1971
|
+
"Return every locale variant of a menu, identified via the shared translation_group.",
|
|
1972
|
+
inputSchema: z.object({
|
|
1973
|
+
id: z.string().describe("Menu id (or translation_group)"),
|
|
1974
|
+
}),
|
|
1975
|
+
annotations: { readOnlyHint: true },
|
|
1976
|
+
},
|
|
1977
|
+
async (args, extra) => {
|
|
1978
|
+
requireScope(extra, "content:read");
|
|
1979
|
+
const ec = getEmDash(extra);
|
|
1980
|
+
try {
|
|
1981
|
+
const { handleMenuTranslations } = await import("../api/handlers/menus.js");
|
|
1982
|
+
return unwrap(await handleMenuTranslations(ec.db, args.id));
|
|
1983
|
+
} catch (error) {
|
|
1984
|
+
return respondHandlerError(error, "MENU_TRANSLATIONS_ERROR");
|
|
1985
|
+
}
|
|
1986
|
+
},
|
|
1987
|
+
);
|
|
1988
|
+
|
|
1863
1989
|
server.registerTool(
|
|
1864
1990
|
"menu_create",
|
|
1865
1991
|
{
|