From 7baa4ee3a356b3df361d7bf655a8045429687c0f Mon Sep 17 00:00:00 2001 From: Jose Antonio Alatorre Date: Thu, 22 Oct 2026 10:47:49 +0200 Subject: [PATCH] Codex plugin 0.3.1: bundle devtools 0.3.1 with stored MCP names Pin @dev-mainsequence/devtools 0.3.1 (lockfile integrity from the registry's dist.integrity) and release the plugin as 0.3.1. devtools 0.3.1 stores a connected MCP's names (name, display_name, code_repository_branch_uid) in the shared mcp-connections.json when mcp-add saves it and lists them without a backend request; a connection saved by an earlier version is completed by the first listing that can read it. The readable /ms output labels the new connection fields; --json passes them to the mainsequence-mcp skill unchanged, and the skill and user guide describe them. CI no longer names a devtools source branch now that the pin is on the registry. Verification is recorded in docs/codex-verification.md (release check, verify:codex and verify:codex:reload in isolated Codex homes). Co-Authored-By: Claude Fable 5.1 --- .github/workflows/ci.yml | 8 ++-- README.md | 9 +++-- docs/codex-verification.md | 37 +++++++++++++++++++ docs/conversational-mcp.md | 2 +- manifests/codex/.codex-plugin/plugin.json | 2 +- .../codex/skills/mainsequence-mcp/SKILL.md | 2 +- package-lock.json | 12 +++--- package.json | 4 +- src/hosts/codexPresentation.ts | 1 + tests/codex.test.cjs | 7 ++++ 10 files changed, 64 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04683b4..2ad1509 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,10 +15,8 @@ jobs: node-version: '22' cache: npm - run: npm install --global npm@11.6.2 - # `npm ci --ignore-scripts` once the pinned devtools is on the registry. Until then - # the pinned version is built from the devtools repository at this ref and checked - # against the lockfile integrity. Remove DEVTOOLS_SOURCE_REF after publication. + # `npm ci --ignore-scripts` while the pinned devtools is on the registry. While a pin is + # not published yet, the script builds it from the devtools repository at its release + # tag and checks the archive against the lockfile integrity. - run: node scripts/install-devtools.cjs - env: - DEVTOOLS_SOURCE_REF: codex/extract-codex-plugin - run: npm run release:check diff --git a/README.md b/README.md index 177bb7b..a86f6e6 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,9 @@ and no model call. Its `mainsequence-mcp` skill lets Codex discover MainSequence MCPs in conversation, remember a selection and use that project's tools through a bundled MCP client. -Version **0.3.0** is the first release from this repository. Until devtools 0.2.8 the plugin -was built and published from +Version **0.3.1** bundles devtools 0.3.1, which stores a connected MCP's names with the saved +connection (see [the release notes](docs/codex-verification.md)). Version 0.3.0 was the first +release from this repository. Until devtools 0.2.8 the plugin was built and published from [mainsequence-devtools](https://github.com/mainsequence-sdk/mainsequence-devtools) under the name `mainsequence-devtools` ([ADR 0003 there](https://github.com/mainsequence-sdk/mainsequence-devtools/blob/main/docs/adr/0003-codex-plugin-extraction.md)). The shared implementation is still that package; this repository owns the hook adapter, the @@ -109,14 +110,14 @@ results. `tests/dependency-boundary.test.cjs` forbids private devtools imports. recorded in `package-lock.json`. While that version is not published yet, run ```sh -node scripts/install-devtools.cjs /path/to/dev-mainsequence-devtools-0.3.0.tgz +node scripts/install-devtools.cjs /path/to/dev-mainsequence-devtools-0.3.1.tgz ``` with the archive from `npm pack` of the devtools release branch, or without an argument to build it from the devtools repository at `DEVTOOLS_SOURCE_REF` (default `v`). Either way the archive must match the lockfile integrity, and the registry pin is not changed (`scripts/use-local-devtools.cjs`). CI does the same until the version is -published. After publication, confirm that `npm view @dev-mainsequence/devtools@0.3.0 +published. After publication, confirm that `npm view @dev-mainsequence/devtools@0.3.1 dist.integrity` equals the lockfile entry before tagging a release; if the registry archive differs, update the lockfile and rebuild so `build-info.json` records the published integrity. diff --git a/docs/codex-verification.md b/docs/codex-verification.md index 0073400..d0545ae 100644 --- a/docs/codex-verification.md +++ b/docs/codex-verification.md @@ -1,5 +1,42 @@ # Codex plugin verification +## 0.3.1 — devtools 0.3.1: MCP names stored with saved connections (2026-10-22) + +The plugin bundles [devtools 0.3.1](https://github.com/mainsequence-sdk/mainsequence-devtools/pull/15) +in place of 0.3.0; the hook adapter, manifest, hooks and skills are otherwise unchanged, so +the hook definition and its trusted hash are the same as in 0.3.0. + +What the new devtools changes for this plugin: + +- `mcp-add` resolves the release's name, its repository's name and its repository branch + and stores them with the saved connection in the shared `mcp-connections.json` as `name`, + `display_name` and `code_repository_branch_uid`. A label that cannot be read is left out; + it never makes a working MCP unavailable. +- `mcp-list` returns the stored labels without a backend request. A connection saved by an + earlier version is completed by the first listing that can read its labels. `mcp-add`, + `mcp-tools` and `mcp-call` results carry them on their connection, and discovery rows pass + the directory's `name` and `code_repository_branch_uid` through. +- The connections file is shared with the Claude Desktop plugin (0.4.18 pins the same + devtools), so a connection labelled by either host is labelled for both. +- The readable `/ms` output labels the new fields (`Release ID`, `Name`, `Repository`, + `Repository branch ID`); `--json` passes the rows to the `mainsequence-mcp` skill unchanged. + +Package checks under Node 22.22.0 and npm 10.9.4, `npm run release:check`: type-check, build +from the registry archive of devtools 0.3.1 (`npm ci --ignore-scripts`; its integrity in +`package-lock.json` and `build-info.json` is the registry's `dist.integrity`), the Node tests +including a new case for the stored MCP connection labels in readable and `--json` output, release metadata, the standalone +archive and the npm archive exercised as Codex installs it. Since the pinned devtools is on +the registry, CI no longer names a devtools source branch; `scripts/install-devtools.cjs` +falls back to the pin's release tag only for an unpublished pin. + +Installed-host checks with the Codex CLI 0.163.0 on macOS, in isolated `CODEX_HOME` +directories, the only model endpoint being the counted loopback fixture: `npm run +verify:codex` against this build installed from `artifacts/local-marketplace` and trusted +(`skills/list` and `hooks/list` as recorded for 0.3.0; all 13 prompt cases and both sync +cases behaved as in the 0.3.0 table below, with zero real model requests), and +`npm run verify:codex:reload` (same three results as for 0.3.0). The hook definition did +not change, so its trusted hash is still `sha256:8935862c…`. + ## 0.3.0 — extraction from devtools and rename to `mainsequence` (2026-10-21) The plugin moved out of [mainsequence-devtools](https://github.com/mainsequence-sdk/mainsequence-devtools) diff --git a/docs/conversational-mcp.md b/docs/conversational-mcp.md index cb98ab5..7c34969 100644 --- a/docs/conversational-mcp.md +++ b/docs/conversational-mcp.md @@ -35,7 +35,7 @@ If no developer session exists, use the existing Main Sequence hosted login. A c Connection metadata lives in mcp-connections.json beside the existing MainSequence CLI configuration, separated by backend and release UID. Reads/calls recheck release access and fetch the current tool catalog. A changed endpoint requires an explicit add again. Removing a connection does not revoke your login. -The release UID identifies a connection. Its optional `name` is a display label from discovery; release detail responses omit it. Adding a connection and reading or calling its tools work without that label, including for saved connections. UID-based operations do not repeat discovery to obtain a name. +The release UID identifies a connection. Since devtools 0.3.1, mcp-add also reads the release's name, its repository's name and its repository branch from the release directory and stores them with the connection as `name`, `display_name` and `code_repository_branch_uid`, so mcp-list labels a saved connection without a backend request; a connection saved by an earlier version is completed by the first listing that can read those labels, and a label that cannot be read is left out rather than making the MCP unavailable. Adding a connection and reading or calling its tools work without the labels, and UID-based operations do not repeat discovery to obtain a name. Discovery rows carry `name` and `code_repository_branch_uid` as the platform directory reports them. Project tools enforce their ordinary permissions. The client adds no agent-specific allowlist or exclusions. diff --git a/manifests/codex/.codex-plugin/plugin.json b/manifests/codex/.codex-plugin/plugin.json index 444d20a..f071579 100644 --- a/manifests/codex/.codex-plugin/plugin.json +++ b/manifests/codex/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "mainsequence", - "version": "0.3.0", + "version": "0.3.1", "description": "Use MainSequence project MCPs from conversation and run explicit developer commands with the bundled runner.", "author": { "name": "MainSequence" diff --git a/manifests/codex/skills/mainsequence-mcp/SKILL.md b/manifests/codex/skills/mainsequence-mcp/SKILL.md index 2bfa024..a02a810 100644 --- a/manifests/codex/skills/mainsequence-mcp/SKILL.md +++ b/manifests/codex/skills/mainsequence-mcp/SKILL.md @@ -12,7 +12,7 @@ This workflow uses a client inside the plugin. Saved project connections can be - For "which MCPs are available?", execute the runner with mcp-discover --json. It calls resource_release.mcp_endpoints on the platform MCP. Use --search TEXT, --limit N (up to 100), and --offset N when needed; count reports the full matching collection. - Show names, release UIDs and Environment UIDs where needed to distinguish results. Discovery alone does not authorize adding every result. - For "add metatable-mcp", identify the exact discovered release. If the name identifies multiple releases, ask which one. Execute mcp-add --uid RELEASE_UUID --json. Success means initialization and tool discovery succeeded and the connection was saved. Use the returned tool catalog immediately. -- For saved connections, execute mcp-list --json. This is local metadata, not a live health report; do not rediscover the whole directory every time the user wants to use one. +- For saved connections, execute mcp-list --json. This is local metadata, not a live health report; do not rediscover the whole directory every time the user wants to use one. Each row carries the release UID with the saved name, display_name (the repository's name) and code_repository_branch_uid when they were readable; use them to label a connection instead of discovering again. - When asked to remove a saved connection, execute mcp-remove --uid RELEASE_UUID --json. This does not revoke the Main Sequence login. All commands accept --backend URL. Use the endpoint already selected for the task; absent an explicit selection, the runner uses the process endpoint, current directory's endpoint, saved CLI configuration, then the standard backend. Connections are separated by backend and release UID. Do not guess or construct project URLs. diff --git a/package-lock.json b/package-lock.json index 289c87f..98cc413 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "@dev-mainsequence/codex-plugin", - "version": "0.3.0", + "version": "0.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@dev-mainsequence/codex-plugin", - "version": "0.3.0", + "version": "0.3.1", "license": "MIT", "bin": { "ms-devtools": "dist/runner.js" }, "dependencies": { - "@dev-mainsequence/devtools": "0.3.0" + "@dev-mainsequence/devtools": "0.3.1" }, "devDependencies": { "@types/node": "18.19.130", @@ -23,9 +23,9 @@ } }, "node_modules/@dev-mainsequence/devtools": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@dev-mainsequence/devtools/-/devtools-0.3.0.tgz", - "integrity": "sha512-0aLOykrjmMgpB0IP5awhqCGiQH0wsNDpblqK7qi3nNPeeYWAW0nyHDL1zANfTlfXhC2EUArEJeCuyIsqANCZQw==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@dev-mainsequence/devtools/-/devtools-0.3.1.tgz", + "integrity": "sha512-Gb8Gva1PZ1/kLCkO7NfEgELKUhakonck2DKQsgyf5N1pEVgHwyFD0zCsjTHOkNEGaOEPVIvSAL7h1BbNexHIOw==", "license": "MIT", "bin": { "ms-devtools": "dist/runner.js" diff --git a/package.json b/package.json index e821547..49a9262 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dev-mainsequence/codex-plugin", - "version": "0.3.0", + "version": "0.3.1", "description": "MainSequence plugin for Codex: /ms developer commands executed before inference and conversational project MCPs", "license": "MIT", "engines": { @@ -36,7 +36,7 @@ "release:check": "npm run typecheck && npm test && node scripts/check-release.cjs && node scripts/pack-codex.cjs && npm pack --ignore-scripts --pack-destination artifacts && npm run verify:package" }, "dependencies": { - "@dev-mainsequence/devtools": "0.3.0" + "@dev-mainsequence/devtools": "0.3.1" }, "devDependencies": { "@types/node": "18.19.130", diff --git a/src/hosts/codexPresentation.ts b/src/hosts/codexPresentation.ts index 7f37f9e..038f04a 100644 --- a/src/hosts/codexPresentation.ts +++ b/src/hosts/codexPresentation.ts @@ -54,6 +54,7 @@ const fieldNames: Record = { dryRun: 'Preview only', endpointOnly: 'Credentials excluded from project files', dependenciesInstalled: 'Dependencies installed', updateAvailable: 'Update available', updateSupported: 'Automatic update supported', dependencyType: 'Dependency type', registryPublicationVerified: 'Registry publication verified', sourceStatus: 'Source version lookup', hint: 'Note', + resource_release_uid: 'Release ID', display_name: 'Repository', code_repository_branch_uid: 'Repository branch ID', }; const hiddenFields = new Set(['gitCommonDir', 'repositoryIdentity', 'ref', 'store', 'sourceUrl', 'dependencyPolicy', 'releaseChannel']); const values: Record = { python: 'Python', vite_react: 'React + Vite', available: 'Available', unavailable: 'Unavailable', unsupported: 'Unsupported', current: 'Up to date', update_available: 'Update available', not_installed: 'Not installed' }; diff --git a/tests/codex.test.cjs b/tests/codex.test.cjs index 180c621..9048595 100644 --- a/tests/codex.test.cjs +++ b/tests/codex.test.cjs @@ -151,6 +151,13 @@ test('Codex repository, session and project results show useful fields without J assert.match(sdk.reason, /Registry publication verified: No/); const structured = await handleCodexPrompt({ prompt: '/ms repositories --json' }, async () => ({ schemaVersion: 1, action: 'repositories', status: 'success', summary: 'repositories completed.', data })); assert.deepEqual(JSON.parse(structured.reason).data, data); + // devtools 0.3.1 stores the release name, the repository name and its branch with a saved MCP connection. + const connection = { backend: 'https://fixture.example', resource_release_uid: '0c7a1a2e-6d7c-4a4e-8d2e-1f3b5c7d9e01', name: 'metatable-mcp', display_name: 'Research', code_repository_branch_uid: '7d9e0c7a-1a2e-4d7c-9a4e-8d2e1f3b5c7d', mcp_connection: { url: 'https://mcp.example/mcp', transport: 'streamable-http' } }; + const added = await handleCodexPrompt({ prompt: '/ms mcp-add --uid 0c7a1a2e-6d7c-4a4e-8d2e-1f3b5c7d9e01' }, async () => ({ schemaVersion: 1, action: 'mcp-add', status: 'success', summary: 'MCP connection verified and saved.', data: { connection, tools: [] } })); + assert.match(added.reason, /Connection\n Backend: https:\/\/fixture\.example\n Release ID: 0c7a1a2e-6d7c-4a4e-8d2e-1f3b5c7d9e01\n Name: metatable-mcp\n Repository: Research\n Repository branch ID: 7d9e0c7a-1a2e-4d7c-9a4e-8d2e1f3b5c7d\n/); + assert.doesNotMatch(added.reason, /display_name|code_repository_branch_uid|resource_release_uid|\{|\}/); + const savedList = await handleCodexPrompt({ prompt: '/ms mcp-list --json' }, async () => ({ schemaVersion: 1, action: 'mcp-list', status: 'success', summary: 'Saved MCP connections for this backend.', data: [connection] })); + assert.deepEqual(JSON.parse(savedList.reason).data, [connection], 'the stored labels reach the mainsequence-mcp skill unchanged'); }); test('a literal --json option value does not request JSON output', async () => {