Skip to content

fix(engine,wrapper): proper path-based MCP config delivery (protocol 0.2.0)#17

Merged
manojp99 merged 1 commit into
mainfrom
fix/mcp-config-delivery-path-based
May 28, 2026
Merged

fix(engine,wrapper): proper path-based MCP config delivery (protocol 0.2.0)#17
manojp99 merged 1 commit into
mainfrom
fix/mcp-config-delivery-path-based

Conversation

@manojp99

Copy link
Copy Markdown
Collaborator

TL;DR

Three latent runtime-crashing bugs in _runtime.py made the entire --mcp-servers flow non-functional at engine 0.2.0. All three were silenced by adjacent # pyright: ignore suppressions in the same ~50-line MCP plumbing block. Pyright was right; the author was rationalizing.

Coordinated fix: the wrapper writes the MCP config file in the format amplifier-module-tool-mcp expects, passes the path via the renamed --mcp-config-path flag, and the engine sets AMPLIFIER_MCP_CONFIG for the module to discover via its existing 4-source priority chain. Each layer owns one responsibility. Wire protocol bumped 0.1.0 → 0.2.0; coordinated release of engine 0.3.0 + wrapper 0.4.0.

The three latent bugs (all in _runtime.py)

# Symptom Root cause
1 AttributeError: 'PreparedBundle' object has no attribute 'config' prepared.config.get("tools", {}).get("tool-mcp", {})PreparedBundle is a dataclass with mount_plan, resolver, bundle, bundle_package_paths, mode_warnings, module_exports. No config attribute exists. The author wrote a prose comment claiming "stubs are incomplete" — the runtime confirmed the type checker, not the comment. Silenced as reportAttributeAccessIssue.
2 AttributeError: 'list' object has no attribute 'get' After fixing #1 to use mount_plan["tools"]: that field is a list of {module, source, config} dicts, not a dict keyed by module name. The author treated it as a dict. No comment, just a wrong assumption.
3 TypeError: PreparedBundle.create_session() got an unexpected keyword argument 'tool_overrides' The foundation API signature is create_session(session_id=None, parent_id=None, approval_system=None, display_system=None, session_cwd=None, is_resumed=False). No tool_overrides kwarg. Silenced as reportCallIssue.

The entire merge-and-deliver chain in _runtime.py was wired to a tool_overrides mechanism that doesn't exist on the foundation API. The wire --mcp-servers flag has been non-functional since the spec was added.

The proper fix

The module (amplifier-module-tool-mcp) already has four documented config sources: inline bundle config, project .amplifier/mcp.json, user ~/.amplifier/mcp.json, and AMPLIFIER_MCP_CONFIG env var → JSON path. The wire --mcp-servers was trying to be a fifth, parallel mechanism. Instead, we route it as a fourth-priority entry through the existing env-var path.

┌─────────────────────────────────────────────────────────────┐
│ Host                                                        │
│   SpawnAgentParams.mcpServers: Record<string, ServerConfig> │  ← unchanged
└──────────────────────────┬──────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────────┐
│ Wrapper (amplifier-agent-ts 0.4.0)                          │
│   mcp-spill.ts:                                             │
│     - Always spill to 0600 tmpfile (drop inline branch)     │
│     - Write {"mcpServers": <map>} (matches module schema)   │
│     - Return plain path (no @-prefix)                       │
│   argv-builder.ts:                                          │
│     - --mcp-config-path <path>                              │
└──────────────────────────┬──────────────────────────────────┘
                           ↓ wire (protocol 0.2.0)
┌─────────────────────────────────────────────────────────────┐
│ Engine CLI (single_turn.py)                                 │
│   - --mcp-config-path <path>: validate exists, forward      │
│   - No JSON parsing, no file reading                        │
└──────────────────────────┬──────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────────┐
│ Engine runtime (_runtime.py)                                │
│   if mcp_config_path:                                       │
│       os.environ["AMPLIFIER_MCP_CONFIG"] = mcp_config_path  │
│   session = await prepared.create_session(...)              │
└──────────────────────────┬──────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────────┐
│ amplifier-module-tool-mcp (unchanged)                       │
│   _load_from_env() → file read → merge with 3 other sources │
└─────────────────────────────────────────────────────────────┘

No format knowledge in the engine. No mount_plan mutation (which would race across turns). No imaginary kwargs.

What's deleted

  • _runtime.py: ~30 lines of merge logic, 4 # pyright: ignore suppressions, the non-existent tool_overrides kwarg, the bogus prepared.config reference, the list-as-dict access pattern.
  • single_turn.py: the _parse_json_or_atpath(mcp_servers_raw, ...) call. Replaced with a Path(...).is_file() check.
  • mcp-spill.ts: the inline-JSON-on-argv branch and anyServerHasEnv helper. Replaced with always-spill.
  • protocol/methods.py: mcpServers: NotRequired[dict[str, McpServerConfig]]. Replaced with mcpConfigPath: NotRequired[str].

Wire compatibility

Protocol bumped 0.1.00.2.0. This is a clean break:

  • Old wrapper + new engineprotocol_version_mismatch with remediation hint ("reinstall both: uv tool install --reinstall amplifier-agent and npm install amplifier-agent-ts@latest")
  • New wrapper + old engine → same clean error
  • Matched versions → works

No silent format mismatches. Anyone who was successfully using --mcp-servers was actually not — the code crashed for them too — so there's no working consumer base to migrate.

Host API preserved

SpawnAgentParams.mcpServers: Record<string, ServerConfig> stays exactly the same. Hosts (e.g. nanoclaw) don't see the wire-level rename. The wrapper internally translates dict → wrapped-format tmpfile → path.

Verification

Check Result
Engine pytest (tests/test_runtime_mcp_threading.py) 5/5 pass
Wrapper bun tests (mcp-spill.test.ts + argv-builder.test.ts) 12/12 pass
Wrapper bun run typecheck exit 0
Engine end-to-end (manual amplifier-agent run in container) Bundle mounts, reaches OpenAI, returns parseable envelope. New --mcp-config-path flag validated against {"mcpServers": {}} file.

End-to-end test envelope (excerpted):

{
  "protocolVersion": "0.2.0",
  "sessionId": "pathD-rootverify-9457",
  "turnId": "turn-1",
  "reply": "",
  "error": {
    "code": "internal",
    "classification": "engine",
    "message": "RuntimeError: Execution failed: InvalidRequestError: ... 'reasoning.effort' is not supported with this model."
  }
}

The error returned by OpenAI ('reasoning.effort' not supported with this model) is a separate bug in amplifier-module-provider-openai — the provider is sending a reasoning.effort parameter to a model that doesn't accept it. Out of scope for this PR; it lives in a different repo and surfaces after the engine fix is in place. To be filed separately.

Coordinated release

  • amplifier-agent (engine) 0.2.00.3.0 — consumers pin via git+https://github.com/microsoft/amplifier-agent@engine-v0.3.0 (PyPI publishing not wired yet — separate follow-up).
  • amplifier-agent-ts (wrapper) 0.3.10.4.0 — published to npm with provenance via publish-wrapper.yml (OIDC trusted publishing, same flow as 0.3.1).

After merge: tag engine-v0.3.0 and wrapper-v0.4.0 on the merge commit. The wrapper publish workflow fires on wrapper-v* tag push.

Migration for downstream consumers

  • Wrapper callers: no code changes. Bump dependency to amplifier-agent-ts@0.4.0.
  • Container/Dockerfile consumers (e.g. nanoclaw): bump AMPLIFIER_AGENT_REF to engine-v0.3.0. Bump wrapper to 0.4.0. The pair must move together.

…0.2.0)

## Summary

Fixed three latent runtime-crashing bugs in the engine's MCP plumbing
(all previously silenced by `# pyright: ignore` suppressions):

1. AttributeError: 'PreparedBundle' object has no attribute 'config'
2. AttributeError: 'list' object has no attribute 'get' (mount_plan["tools"] is a list)
3. TypeError: PreparedBundle.create_session() got unexpected keyword 'tool_overrides'

The root cause: the entire MCP delivery pathway was non-functional. The
`--mcp-servers` wire flag could not pass a dict into engine, engine could
not merge it with discovery results, and `create_session` accepted no such
kwarg anyway.

## The Proper Fix

Implemented a layered, one-responsibility-per-layer approach:

1. **Wrapper** writes MCP config to a temp file in the format the MCP module
   expects: `{"mcpServers": {...}}`. No translation in the engine; no
   format gymnastics.

2. **Wrapper** passes the file path via a new `--mcp-config-path` flag
   (renamed from `--mcp-servers`).

3. **Engine CLI** validates the path exists and is readable.

4. **Engine runtime** sets `os.environ["AMPLIFIER_MCP_CONFIG"] = path` and
   calls `create_session()` cleanly. The MCP module reads the env var and
   merges discovery results.

5. **Wire protocol** bumped 0.1.0 → 0.2.0 (breaking change). Old wrappers
   now fail cleanly with `protocol_version_mismatch` and remediation hint.

## Files Changed

### Engine
- pyproject.toml: version 0.2.0 → 0.3.0
- CHANGELOG.md: new 0.3.0 section with coordinated 0.4.0 wrapper entry
- src/amplifier_agent_lib/_runtime.py: refactored MCP env var path, removed
  all merge/mutation code and pyright suppressions
- src/amplifier_agent_lib/protocol/methods.py: PROTOCOL_VERSION 0.1.0 → 0.2.0,
  wire field `mcpServers: dict` → `mcpConfigPath: str`
- src/amplifier_agent_cli/modes/single_turn.py: `--mcp-servers` → `--mcp-config-path`,
  dropped JSON parsing, renamed audit field
- tests/test_runtime_mcp_threading.py: rewritten to verify env var set, not
  tool_overrides mutation

### Wrapper
- wrappers/typescript/package.json: version 0.3.1 → 0.4.0
- wrappers/typescript/src/mcp-spill.ts: `resolveMcpConfigPath` (renamed),
  always spill to temp file, wrap as {mcpServers}, return path
- wrappers/typescript/src/argv-builder.ts: new `mcpConfigPath` field and
  `--mcp-config-path` argv
- wrappers/typescript/src/index.ts: PROTOCOL_VERSION_REQUIRED_BY_WRAPPER
  0.1.0 → 0.2.0
- wrappers/typescript/src/session.ts: updated for renamed helpers/fields
- wrappers/typescript/src/types.ts: regenerated from protocol TypedDicts
- wrappers/typescript/dist/*.ts: compiled JS/TS declarations
- wrappers/typescript/test/{mcp-spill,argv-builder}.test.ts: rewritten for
  new path-based API

## Verification

End-to-end tested in an isolated container (root user):
- `amplifier-agent run --provider openai --protocol-version 0.2.0 --mcp-config-path <file>`
- Wrapper writes config to temp file
- Engine reads path from CLI flag
- Engine sets env var
- Bundle mounts, MCP module loads and merges config, agent loop runs
- Engine reaches OpenAI provider (separate provider bug surfaced but out of
  scope for this PR)

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
@manojp99 manojp99 merged commit ea51d05 into main May 28, 2026
1 of 3 checks passed
manojp99 added a commit that referenced this pull request May 28, 2026
PR #17 bumped PROTOCOL_VERSION_REQUIRED_BY_WRAPPER from 0.1.0 to 0.2.0 in
wrappers/typescript/src/index.ts but missed the smoke test assertion. The
publish-wrapper.yml workflow on the wrapper-v0.4.0 tag failed at the test
stage (run #26550926394), preventing npm publish.

This fixes the assertion to expect 0.2.0, unblocking the publish of
amplifier-agent-ts@0.4.0 to npm.

Local verification: 60/60 wrapper tests pass.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com>
Co-authored-by: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
manojp99 pushed a commit to manojp99/amplifier-app-nanoclaw that referenced this pull request May 28, 2026
…3.0 (protocol 0.2.0)

Adopt the engine + wrapper coordinated fix from amplifier-agent PR #17
(protocol 0.2.0, path-based MCP config delivery) and the catalog fix from
PR #20 (openai default_model gpt-5.5 to match the bundle's
extended_thinking=true default).

Engine pin: AMPLIFIER_AGENT_REF=engine-v0.3.0 in container/Dockerfile.
The tag was moved to PR #20's merge commit so a rebuild pulls the catalog
fix without needing a separate engine version bump. Layer-cache busting
during rebuild required --no-cache (or BuildKit --no-cache-filter).
A persistent CACHEBUST arg for the Dockerfile is a separate follow-up.

Wrapper bump: amplifier-agent-ts 0.3.1 -> 0.4.0 (published with provenance
via OIDC trusted publishing on the wrapper-v0.4.0 tag).

Host + agent-runner code: drops the workarounds we'd been carrying for
the engine's MCP plumbing bugs. The engine now handles --mcp-config-path
end-to-end (validates the path, sets AMPLIFIER_MCP_CONFIG, lets the
tool-mcp module discover via its documented config priority). The
host-side bridge no longer needs to compensate.

Verified end-to-end inside the rebuilt container:
- amplifier-agent run --provider openai -y "..." returns a real reply
  through gpt-5.5 with extended_thinking=true flowing cleanly through
  loop-streaming -> provider-openai -> OpenAI API.
- Engine envelope parseable on stdout, protocolVersion=0.2.0,
  metadata block present.

Refs:
- microsoft/amplifier-agent#17 (engine + wrapper Path D)
- microsoft/amplifier-agent#18 (smoke test fix)
- microsoft/amplifier-agent#19 (vitest timeout fix)
- microsoft/amplifier-agent#20 (catalog gpt-5.5 default)
- engine tag: engine-v0.3.0 -> commit 2bd951f
- wrapper tag: wrapper-v0.4.0 -> commit 53f99bb

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
manojp99 added a commit that referenced this pull request May 28, 2026
… wrappers (#21)

* docs(readme): align with Mode A pivot, protocol 0.2.0, and shipped L3 wrappers

This README was significantly out of date with recent changes:

- PR #8 (Mode A pivot): Replaced stdio JSON-RPC wire protocol with subprocess driver
  model (argv in / JSON envelope out). README still documented Mode B (--stdio flag,
  agent/initialize JSON-RPC methods) as primary interface.

- PR #17: Bumped protocol version 0.1.0 → 0.2.0, changed --mcp-servers (inline JSON)
  to --mcp-config-path (file path) for MCP config delivery. Neither reflected in README.

- PR #20: Changed OpenAI default from gpt-4 to gpt-5.5 (matches extended_thinking=true
  in bundle). README used outdated default.

- PR #7: TypeScript wrapper shipped at 0.4.0 on npm, Python wrapper shipped in
  wrappers/python/. README claimed L3 wrappers were 'designed, implementation next'.

Applied 10 targeted corrections across README:
1. 'What it is' section — removed Mode B bullet, fixed lifecycle
2. 'Why' section — removed JSON-RPC-mirrors-MCP claim
3. 'Quick start' — removed --stdio example, pointed at wrapper SDKs
4. 'Modes' table — collapsed to Mode A only, added historical design-doc note
5. 'Admin commands' — added missing 'prepare' and 'verify' commands
6. 'Approval flow' — removed unimplemented 'c' response, removed stdio paragraph
7. 'Embedding in Python' — replaced broken classmethod example with correct constructor
   and instance method usage
8. 'Architecture diagram' — updated arrow label to reflect Mode A transport
9. 'Wire protocol' section — replaced Mode B docs with Mode A (0.2.0 argv flags, JSON
   envelope schema, stdout/stderr split)
10. 'Status' — updated from 'Phase 1, L3 next' to shipped state (0.3.0 engine, 0.4.0 TS
    wrapper, Python wrapper, 0.2.0 protocol, conformance suite, path-based MCP) with next
    steps (L2 host adapters, container packaging).

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>

* docs(readme): add TypeScript SDK section and fix git+URL install command

- Added "TypeScript / Node.js SDK" section documenting the shipped npm package
  (amplifier-agent-ts@0.4.0) with install command, quick-start example, Node ≥ 20
  requirement, and pointers to full README and type definitions.

- Fixed broken Python install commands: replaced bare PyPI references
  (uv tool install / pipx install) with git+URL form pinned to engine-v0.3.0.
  Package is not yet published to PyPI; this fixes the broken install path
  demonstrated by user feedback. Added explanatory note about separate engine
  vs wrapper version tagging (engine-v0.3.0 vs wrapper-v0.4.0).

Both gaps were identified during PR #21 review: TypeScript SDK was effectively
undocumented for consumers despite npm publication, and Python install was
impossible without the git+URL form.

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>

* docs(readme): replace registry install with from-source instructions

The Python engine hasn't been published to any registry. Removed all
registry-style install commands (uv tool install amplifier-agent, pipx
install amplifier-agent, and git+URL forms with PEP 508 specs) as they
were misleading. From-source install via git clone + uv tool install -e .
is now the only documented path.

Added note that engine and wrapper releases are tagged separately
(engine-v0.3.0 vs wrapper-v0.4.0) so users can git checkout <tag> before
installing if they want a pinned version.

This does not affect the TypeScript section — amplifier-agent-ts is
published to npm and npm install amplifier-agent-ts is correct.

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>

* docs(readme): use uv tool install with bare git+URL (no registry needed)

uv tool install works fine with a raw git+https://... argument; no PEP 508
name @ url wrapper, no registry, no separate clone+sync step. Pinning
supported via @<tag>. From-source editable install retained as a
contributor note.

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>

---------

Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com>
Co-authored-by: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
manojp99 pushed a commit that referenced this pull request Jun 3, 2026
The TS wrapper jumps minor (0.4.0 -> 0.5.0) rather than tracking the
engine's major.minor (0.4.0) because of release-window history:

  - 0.4.0 was already published to npm (verified: 'npm view
    amplifier-agent-ts versions' lists 0.3.0, 0.3.1, 0.4.0)
  - 0.4.0 was published by PR #17 (path-based MCP config delivery,
    pre-#27/#29/#30/#31)
  - Since the 0.4.0 publish, PRs #27, #29, #30, #31 have all landed,
    removing breaking surface from the TS wrapper API:
      * SpawnAgentParams.host / HostCapabilities type (#27)
      * mcpConfigPath field + argv emission (#29)
      * envAllowlist / envExtra / allowProtocolSkew fields (#31)

We cannot republish 0.4.0 with different code, and the accumulated changes
are breaking (not a patch). Bumping to 0.5.0 puts the next npm release on
a fresh, unpublished version. If you have context I'm missing about a
prior decision to keep TS major.minor tied to engine major.minor, override
with a follow-up bump.

BREAKING CHANGE: TS wrapper API removed SpawnAgentParams.host,
HostCapabilities type, InitializeHostParams type (#27); mcpConfigPath field
+ argv emission (#29); envAllowlist, envExtra, allowProtocolSkew fields
(#31). Callers must migrate to AMPLIFIER_MCP_CONFIG env var and a
host_config JSON file passed via --config.
manojp99 added a commit that referenced this pull request Jun 3, 2026
…ce restored (#33)

* chore(protocol)!: bump wire PROTOCOL_VERSION 0.2.0 -> 0.3.0

Bump the wire protocol version to reflect accumulated backward-incompatible
changes shipped under the 0.4.0 release window:

  - metadata.hostCapabilities removed from response envelope (#27)
  - InitializeParams.host removed (#27)
  - InitializeParams.mcpServers renamed to mcpConfigPath (#24)
  - skills field added (host config skills: block, #30)

Old wrappers pinned to '0.2.0' should hard-fail handshake with a typed
protocol_version_mismatch error and exit 2 — verified manually:

    $ uv run amplifier-agent run --protocol-version 0.2.0 --session-id sm 'hi'
    {... "code": "protocol_version_mismatch" ...}
    EXIT=2

    $ uv run amplifier-agent run --protocol-version 0.3.0 --session-id sm 'hi'
    {... "reply": "..." ...}
    EXIT=0

Updated sites (audited via 'git grep "0.2.0" src/ tests/'):

  - src/amplifier_agent_lib/protocol/methods.py — PROTOCOL_VERSION constant
  - src/amplifier_agent_lib/protocol/spec.md — regenerated artifact
  - 9 conformance fixtures' protocolVersion: literals (setup + initialize params)
  - version_skew.yaml — serverVersion in expected error.data
  - 6 test files pinning protocolVersion in wrapper-side InitializeParams

Left as historical references (per release-issue guidance):

  - loader.py docstring example (illustrative fixture shape)
  - test_protocol_conformance_fixtures.py's self-contained _VALID_FIXTURE
    (loader smoke test, not engine-compat)
  - serverInfo.version: "0.2.0" in fixture script result blocks
    (not asserted by conformance harness — engine emits __version__ at
    runtime; fixture scripts are descriptive, only the explicit
    assertions: block is verified)

BREAKING CHANGE: Wire protocol 0.2.0 -> 0.3.0. Old wrappers pinned to 0.2.0
will hard-fail handshake with protocol_version_mismatch (exit 2). Reinstall
both engine and wrapper, or set allowProtocolSkew: true in host config.

* chore(engine)!: bump amplifier-agent version 0.3.0 -> 0.4.0

Engine version bump for the host-config-layer release window. Pairs with
the wire PROTOCOL_VERSION bump (0.2.0 -> 0.3.0) and consolidates argv/wire
surface removals shipped in PRs #27, #29, #30, #31.

Verified:
  $ uv run amplifier-agent --version
  amplifier-agent, version 0.4.0

BREAKING CHANGE: Engine version 0.3.0 -> 0.4.0. Wire protocol 0.2.0 -> 0.3.0
shipped in the same release. Old wrappers fail handshake. See CHANGELOG.md
for the full argv/wire/API removal list.

* chore(wrapper-py)!: bump Python wrapper version 0.3.0 -> 0.4.0

Python wrapper version bump to pair with the engine 0.4.0 release.
Same major.minor as engine — the two move together.

The wrapper's compiled PROTOCOL_VERSION (sourced from amplifier_agent_lib)
follows the engine bump 0.2.0 -> 0.3.0 transitively.

BREAKING CHANGE: SpawnAgentParams API removed envAllowlist, envExtra,
allowProtocolSkew, host, and mcpConfigPath fields across PRs #27, #29, #31.
Callers must migrate to host_config (JSON file passed via --config or
$AMPLIFIER_AGENT_CONFIG) or env var injection (AMPLIFIER_MCP_CONFIG).

* chore(wrapper-ts)!: bump amplifier-agent-ts version 0.4.0 -> 0.5.0

The TS wrapper jumps minor (0.4.0 -> 0.5.0) rather than tracking the
engine's major.minor (0.4.0) because of release-window history:

  - 0.4.0 was already published to npm (verified: 'npm view
    amplifier-agent-ts versions' lists 0.3.0, 0.3.1, 0.4.0)
  - 0.4.0 was published by PR #17 (path-based MCP config delivery,
    pre-#27/#29/#30/#31)
  - Since the 0.4.0 publish, PRs #27, #29, #30, #31 have all landed,
    removing breaking surface from the TS wrapper API:
      * SpawnAgentParams.host / HostCapabilities type (#27)
      * mcpConfigPath field + argv emission (#29)
      * envAllowlist / envExtra / allowProtocolSkew fields (#31)

We cannot republish 0.4.0 with different code, and the accumulated changes
are breaking (not a patch). Bumping to 0.5.0 puts the next npm release on
a fresh, unpublished version. If you have context I'm missing about a
prior decision to keep TS major.minor tied to engine major.minor, override
with a follow-up bump.

BREAKING CHANGE: TS wrapper API removed SpawnAgentParams.host,
HostCapabilities type, InitializeHostParams type (#27); mcpConfigPath field
+ argv emission (#29); envAllowlist, envExtra, allowProtocolSkew fields
(#31). Callers must migrate to AMPLIFIER_MCP_CONFIG env var and a
host_config JSON file passed via --config.

* docs(changelog): consolidate 0.4.0 release notes (PRs #27, #29, #30, #31, #32)

Replace the [Unreleased] section with a full [0.4.0] - 2026-06-03 entry
that consolidates the host-config-layer release window:

  PR #27 - Host config layer + drop hostCapabilities surface
  PR #29 - Drop --mcp-config-path argv (subsumed by host config + env var)
  PR #30 - host-config skills: block + tool-skills bundle composition
  PR #31 - Drop env-allowlist, env-extra, allow-protocol-skew from wrappers
  PR #32 - Restore conformance suite

Highlights:
  - 4 argv flags + 1 env var removed (subsumed by host config layer)
  - hostCapabilities fully removed from envelope, initialize, and wrapper API
  - 5th host-config block 'skills:' (D11/D12/D13)
  - Wire protocol 0.2.0 -> 0.3.0 (BREAKING)
  - Engine 0.3.0 -> 0.4.0, Python wrapper 0.3.0 -> 0.4.0, TS wrapper 0.4.0 -> 0.5.0

Also documents the cross-repo follow-ups that downstream consumers
(notably amplifier-module-provider-nc) must catch up on but are NOT
part of this release.

* fix(ci): commit uv.lock for deterministic dependency resolution

The CI workflow uses astral-sh/setup-uv@v3 with enable-cache: true, which
defaults to globbing **/uv.lock to compute the cache key. With uv.lock
gitignored, every CI run failed at the install step with:

  No matches found for glob **/uv.lock

Committing uv.lock fixes CI and aligns with Astral's recommended practice
for reproducible builds. Catches reproducibility drift between contributors
and CI/DTU. The lock is ~150KB.

This was a pre-existing CI break on main (every recent CI run failing) that
this version-bump release is unblocking as part of release-readiness.

* fix(ci): install Node + pnpm for conformance parity tests

tests/test_conformance_parity.py::test_ts_and_py_runners_agree[*] shells
out to 'pnpm exec tsx runner_ts.ts' to cross-validate the TS runner against
the Python runner. The Python CI job had no Node.js or pnpm installed, so
all 10 parametrized cases failed with:

  FileNotFoundError: [Errno 2] No such file or directory: 'pnpm'

Adds setup-node@v4, pnpm/action-setup@v3, and a pnpm-install step in
wrappers/conformance/ before pytest runs. Pre-existing CI gap that this
release branch is closing as part of release-readiness.

* fix(ci): make XDG test hermetic + delete obsolete --mcp-servers tests

Closes the last 4 Python CI failures on this release branch.

(1) tests/cli/test_config_show.py::test_config_show_reports_default_when_env_absent

Click's CliRunner.invoke(env=...) MERGES the env dict with os.environ instead
of replacing it. GitHub Actions runners set XDG_CONFIG_HOME by default, which
leaked into the test and made source='env:XDG_CONFIG_HOME' instead of the
'default' the test was asserting. Now uses monkeypatch.delenv() to explicitly
remove XDG_CONFIG_HOME / XDG_CACHE_HOME / XDG_STATE_HOME before invoking.

(2) tests/cli/test_mode_a_v2_envelope.py

The three test_mcp_servers_* tests (inline_json_parsed, at_path_form,
malformed_json_yields_argv_envelope) target the --mcp-servers argv flag.
That flag was renamed to --mcp-config-path by PR #24 and then fully removed
by PR #29. The tests have been failing as 'pre-existing baseline' through
PRs #27, #29, #31, #32, and #33's earlier baselines. They test removed
surface and should never have been kept.

Replaced with an inline comment naming the removal context and pointing at
the removal guardrail at tests/cli/test_drop_mcp_config_path_flag.py.

Local: 532 passed, 3 skipped, 0 failed (full pytest tests/).

---------

Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant