Skip to content

feat: render MCP config into each target's MCP dialect - #37

Merged
steve-calvert-glean merged 2 commits into
mainfrom
feat/mcp-dialects
Oct 19, 2026
Merged

steve-calvert-glean merged 2 commits into
mainfrom
feat/mcp-dialects

Conversation

@steve-calvert-glean

Copy link
Copy Markdown
Contributor

First of three PRs adding Agent Plugins support. This one builds the MCP piece and changes no output for configs that already work.

Why

Authored MCP config was copied verbatim into every target. The README said pluginpack "translates the configuration into each target's native MCP layout", but only the file path changed. Each client expects different variable names (${CLAUDE_PLUGIN_ROOT}, ${CURSOR_PLUGIN_ROOT}, ${PLUGIN_ROOT}), so authors forked mcp/config.json per target. gleanwork/agent-plugins keeps overrides/codex/glean/mcp/config.json for exactly this. Agent Plugins output needs $schema, an explicit type, and spec-valid fields, so this has to be fixed before that format can be emitted.

What

  • src/mcp.ts: renderMcpConfig(servers, dialect, context) holds every client's MCP dialect: variable names, transport labels, and the Agent Plugins 1.0 rules.
  • Each target sets one mcpDialect; the engine renders through the module.
Dialect Root / data variables Transport
claude ${CLAUDE_PLUGIN_ROOT} / ${CLAUDE_PLUGIN_DATA} streamable-http → http
cursor ${CURSOR_PLUGIN_ROOT} / none (build error) type dropped for stdio/HTTP (Cursor infers it)
copilot ${PLUGIN_ROOT} / as authored streamable-http → http
verbatim as authored (codex, antigravity for now) as authored
agent-plugins ${PLUGIN_ROOT} / ${PLUGIN_DATA} + $schema explicit type; spec §7.2 / §9 enforced

The agent-plugins dialect turns anything a conforming client would silently skip into a build error: a shell string as command, ${API_TOKEN} in env (left unexpanded), plain http to a remote host, reserved env names, or a cwd that escapes the plugin. No target uses this dialect yet; the next PR switches codex to it.

Also adds CONTEXT.md (glossary) and docs/adr/0001 (codex emits Agent Plugins packages by default, with no dual layout).

Behavior change

  • Cursor: ${PLUGIN_DATA} / ${CLAUDE_PLUGIN_DATA} in MCP config is now a build error. Cursor has no plugin-data variable, so that config never worked there.
  • Claude/Cursor: a ./bin/server command becomes ${<root variable>}/bin/server.
  • Config already in a target's own dialect is emitted unchanged.

Verification

  • npm run check passes (239 tests; 40 new in tests/mcp.test.ts, plus one build-level wiring test).
  • Built gleanwork/agent-plugins with released 0.11.0 and with this branch (temp copies): all 191 output files are byte-identical, including the claude, cursor, and codex .mcp.json files.
  • Rendering Glean's shared config in the agent-plugins dialect gives valid Agent Plugins mcp.json. The current codex override is rejected because its cwd: "." isn't a valid Agent Plugins path.

Next

  • (b) Agent Plugins package module, a codex format option (default agent-plugins), a standalone agent-plugins target, and pinned 1.0.0 schemas. Release as 0.12.0.
  • (c) agent-plugins: delete the codex MCP override, convert the shared config, and regenerate codex-plugins.

Authored MCP config was copied verbatim into every target, so authors
forked mcp/config.json per target just to change a plugin-root variable,
and nothing checked the result.

Add src/mcp.ts, which owns every client's MCP dialect: plugin-root and
plugin-data variable names and transport labels. Each target names one
mcpDialect and the engine renders through the module.

- claude: ${CLAUDE_PLUGIN_ROOT}/${CLAUDE_PLUGIN_DATA}; streamable-http -> http
- cursor: ${CURSOR_PLUGIN_ROOT}; type dropped for stdio/HTTP; plugin-data
  variables are a build error (Cursor has none)
- copilot: ${PLUGIN_ROOT}; streamable-http -> http
- codex, antigravity: verbatim (codex moves to Agent Plugins next)
- agent-plugins: Agent Plugins 1.0 mcp.json with $schema, validated
  against spec 7.2/9 (not yet used by a target)

Config already in a target's dialect is unchanged: building
gleanwork/agent-plugins with 0.11.0 and with this change produces
byte-identical output (191 files).

Also adds CONTEXT.md (glossary) and ADR 0001 (codex emits Agent Plugins
packages by default, with no dual layout).
steve-calvert-glean added a commit that referenced this pull request Oct 19, 2026
Fixes from a self-review of the #37 + #38 stack.

- F3: validate parsed SKILL.md frontmatter with gray-matter's default
  engines, so a ---js block ran through eval(). A shared parseMatter()
  helper now refuses the js and javascript engines, for every target.
- F13: build could emit a plugin.json that validate rejects (a bad
  extension namespace, extra author fields). placeClientFields now runs
  the same manifest checks and fails the build.
- F6: native dialects kept an Agent Plugins "./server" cwd as a bare
  relative path, which clients resolve against the user's project. It
  now becomes ${<root>}/server, like a ./ command.
- F8: the agent-plugins target dropped scripts/ by default while still
  emitting MCP commands that point into it. scripts is now a default
  component, as it is for codex.
- F1: validate re-rendered mcp.json and kept only render errors, so a
  server without "type" or with "http" passed. It now reports any server
  that is not already in normalized Agent Plugins form.
- F15: add a test for default-format codex output with hooks/.
- F9, F17, F18, F21: README upgrade note covers the MCP build errors,
  the MCP rules list is complete, install-snippet docs name
  agent-plugins, and CLAUDE.md agrees with CONFORMANCE.md on schemas.
@steve-calvert-glean
steve-calvert-glean merged commit cf093a9 into main Oct 19, 2026
3 checks passed
@steve-calvert-glean
steve-calvert-glean deleted the feat/mcp-dialects branch October 19, 2026 22:48
steve-calvert-glean added a commit that referenced this pull request Oct 19, 2026
Fixes from a self-review of the #37 + #38 stack.

- F3: validate parsed SKILL.md frontmatter with gray-matter's default
  engines, so a ---js block ran through eval(). A shared parseMatter()
  helper now refuses the js and javascript engines, for every target.
- F13: build could emit a plugin.json that validate rejects (a bad
  extension namespace, extra author fields). placeClientFields now runs
  the same manifest checks and fails the build.
- F6: native dialects kept an Agent Plugins "./server" cwd as a bare
  relative path, which clients resolve against the user's project. It
  now becomes ${<root>}/server, like a ./ command.
- F8: the agent-plugins target dropped scripts/ by default while still
  emitting MCP commands that point into it. scripts is now a default
  component, as it is for codex.
- F1: validate re-rendered mcp.json and kept only render errors, so a
  server without "type" or with "http" passed. It now reports any server
  that is not already in normalized Agent Plugins form.
- F15: add a test for default-format codex output with hooks/.
- F9, F17, F18, F21: README upgrade note covers the MCP build errors,
  the MCP rules list is complete, install-snippet docs name
  agent-plugins, and CLAUDE.md agrees with CONFORMANCE.md on schemas.
steve-calvert-glean added a commit that referenced this pull request Oct 20, 2026
…s target (#38)

* feat!: emit Agent Plugins packages from codex and add an agent-plugins target

Agent Plugins 1.0 standardizes the plugin package: a closed root
plugin.json, skills/, mcp.json, and reverse-domain extension namespaces.
OpenAI now prefers it for Codex and ChatGPT and keeps
.codex-plugin/plugin.json only as a fallback.

- src/agent-plugins.ts: the package module. It builds the portable
  manifest, moves client fields under extensions[<namespace>], and
  validates a package against the spec (closed manifest, plugin name,
  mcp.json, and skill names per the Agent Skills spec).
- codex: emits a package by default (root plugin.json with OpenAI
  settings under extensions.com.openai, plus mcp.json) and keeps
  .agents/plugins/marketplace.json. format: "legacy" keeps the
  .codex-plugin layout; validate detects the layout per plugin.
- agent-plugins: a new standalone target that writes portable packages
  only, with no marketplace and no client profile. Client-only content
  kinds are a config error; non-portable manifest fields are a build
  error.
- Targets can now choose a definition per config (forConfig) and post-
  process the merged manifest (finalizeManifest).
- Vendors the official 1.0.0 schemas (with provenance) as the
  conformance oracle for codex and agent-plugins.

BREAKING CHANGE: the codex target's default output layout changes from
.codex-plugin/plugin.json + .mcp.json to an Agent Plugins package
(plugin.json + mcp.json). Set `format: "legacy"` on the codex target to
keep the previous layout. MCP config and skill names that Agent Plugins
clients would skip now fail build or validate.

* fix: address self-review findings

Fixes from a self-review of the #37 + #38 stack.

- F3: validate parsed SKILL.md frontmatter with gray-matter's default
  engines, so a ---js block ran through eval(). A shared parseMatter()
  helper now refuses the js and javascript engines, for every target.
- F13: build could emit a plugin.json that validate rejects (a bad
  extension namespace, extra author fields). placeClientFields now runs
  the same manifest checks and fails the build.
- F6: native dialects kept an Agent Plugins "./server" cwd as a bare
  relative path, which clients resolve against the user's project. It
  now becomes ${<root>}/server, like a ./ command.
- F8: the agent-plugins target dropped scripts/ by default while still
  emitting MCP commands that point into it. scripts is now a default
  component, as it is for codex.
- F1: validate re-rendered mcp.json and kept only render errors, so a
  server without "type" or with "http" passed. It now reports any server
  that is not already in normalized Agent Plugins form.
- F15: add a test for default-format codex output with hooks/.
- F9, F17, F18, F21: README upgrade note covers the MCP build errors,
  the MCP rules list is complete, install-snippet docs name
  agent-plugins, and CLAUDE.md agrees with CONFORMANCE.md on schemas.

* fix: report broken and deep Agent Plugins packages in validate

Resolves the self-review findings that needed a decision.

- F2: findPackages stopped at depth 4, so validate missed a package at
  a valid deeper plugin path. The depth cap is gone; the walk still stops
  at each package and skips node_modules and dot-directories.
- F7: a plugin.json that failed to parse or declared another $schema was
  not treated as a package. Codex then blamed a missing
  .codex-plugin/plugin.json, and the agent-plugins target skipped the
  plugin. Both now validate the root plugin.json and report it.
- F10: the README now says Cursor output drops "type" from stdio and
  HTTP servers, instead of claiming native config is always unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant