diff --git a/package.json b/package.json index 319762c..5c1ea8d 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "dependencies": { "@anthropic-ai/sdk": "^0.112.1", "@aws-sdk/client-s3": "^3.1076.0", - "@contentrain/mcp": "2.0.1", + "@contentrain/mcp": "2.1.0", "@contentrain/query": "^7.0.1", "@contentrain/types": "0.9.0", "@gitbeaker/rest": "^43.8.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c18a39f..05e75cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,8 +23,8 @@ importers: specifier: ^3.1076.0 version: 3.1076.0 '@contentrain/mcp': - specifier: 2.0.1 - version: 2.0.1(@gitbeaker/rest@43.8.0)(@octokit/rest@22.0.1) + specifier: 2.1.0 + version: 2.1.0(@gitbeaker/rest@43.8.0)(@octokit/rest@22.0.1) '@contentrain/query': specifier: ^7.0.1 version: 7.0.1 @@ -668,8 +668,8 @@ packages: resolution: {integrity: sha512-7zVFCDB2reMvJH5dmbKnOQPjZEvjdJTH8jc0U/PIPU1r3/+vf5pD1HlfitV2MWsWXrvu7u39iY1lyLUPOaN0Gw==} engines: {node: '>=22.12.0'} - '@contentrain/mcp@2.0.1': - resolution: {integrity: sha512-4YCll0xjLVx/jcj/aGX5fiwu0fRD5Y3fI3/uW36nSkkYfqKvZm7OwshPYcWEApev9TjNa/9qso3eMjQ6M+f91A==} + '@contentrain/mcp@2.1.0': + resolution: {integrity: sha512-f36pFxcRAj87p4dIcfR0rasBm+FWnB7QC+X556cBoZVMbPaIdta0lZByuYHlMX3LQ7awftuEizuDgZ/Ox5eNPQ==} hasBin: true peerDependencies: '@gitbeaker/rest': '>=43.0.0' @@ -7822,7 +7822,7 @@ snapshots: conventional-commits-parser: 7.1.0 picocolors: 1.1.1 - '@contentrain/mcp@2.0.1(@gitbeaker/rest@43.8.0)(@octokit/rest@22.0.1)': + '@contentrain/mcp@2.1.0(@gitbeaker/rest@43.8.0)(@octokit/rest@22.0.1)': dependencies: '@contentrain/types': 0.9.0 '@modelcontextprotocol/sdk': 1.27.1(zod@3.25.76) @@ -7833,7 +7833,7 @@ snapshots: '@astrojs/compiler': 2.13.1 '@gitbeaker/rest': 43.8.0 '@octokit/rest': 22.0.1 - '@vue/compiler-sfc': 3.5.39 + '@vue/compiler-sfc': 3.5.40 svelte: 4.2.20 transitivePeerDependencies: - '@cfworker/json-schema' diff --git a/server/utils/content-paths.ts b/server/utils/content-paths.ts index 109484d..05022b3 100644 --- a/server/utils/content-paths.ts +++ b/server/utils/content-paths.ts @@ -1,6 +1,6 @@ import type { ModelDefinition } from '@contentrain/types' import { CONTENTRAIN_DIR, PATH_PATTERNS } from '@contentrain/types' -import { contentFilePath, documentFilePath, metaFilePath } from '@contentrain/mcp/core/ops' +import { contentDirPath, contentFilePath, documentFilePath, metaFilePath } from '@contentrain/mcp/core/ops' /** * Resolve file paths for Contentrain content operations. @@ -12,8 +12,7 @@ import { contentFilePath, documentFilePath, metaFilePath } from '@contentrain/mc * across locales instead of pinning to the default locale. Studio keeps only * what MCP's helpers deliberately don't cover: the `contentRoot` prefix, the * `content_path` security hardening, and the "return the directory when a - * document has no slug" case (MCP requires a slug and does not export its - * `contentDirPath`). + * document has no slug" case (MCP requires a slug). */ export interface PathContext { @@ -52,18 +51,18 @@ function assertSafeContentPath(model: Pick): vo } /** - * Content directory (content-root-relative) for a model. Mirrors MCP's - * `contentDirPath` (`@contentrain/mcp/core/ops`, not publicly exported): a - * `content_path` override moves files OUTSIDE `.contentrain/`, otherwise they - * live under the model id. Prefixed with the project's content root. + * Content directory (content-root-relative) for a model. Delegates the dir + * computation to MCP's `contentDirPath` (`@contentrain/mcp/core/ops`, exported + * since 2.1.0) so the `content_path` override / default layout can never drift + * from MCP's write path. Studio adds only the `content_path` security guard and + * the project content-root prefix — neither of which MCP's helper covers. */ function resolveContentDirForModel( ctx: PathContext, model: Pick, ): string { assertSafeContentPath(model) - const dir = model.content_path ?? `${CONTENTRAIN_DIR}/content/${model.domain}/${model.id}` - return prefixed(ctx.contentRoot, dir) + return prefixed(ctx.contentRoot, contentDirPath(model)) } /**