Skip to content

release: prepare v0.4.0 HTTP transport release#29

Merged
marmar9615-cloud merged 1 commit intomainfrom
release/v0.4.0-http-polish
Apr 28, 2026
Merged

release: prepare v0.4.0 HTTP transport release#29
marmar9615-cloud merged 1 commit intomainfrom
release/v0.4.0-http-polish

Conversation

@marmar9615-cloud
Copy link
Copy Markdown
Owner

v0.4.0 implementation PR 3 — release polish + lockstep version bump

  • HTTP smoke + CLI surface. Brings the v0.4.0 release line into a
    publishable state. Nothing is published; no git tag, no GitHub
    release.
    Publishing happens through the existing Trusted
    Publishing workflow only after maintainer approval.

Refs #22.

Predecessor PRs

  • #23 — design + ADR
  • #24 — transport abstraction (createMcpServer() factory)
  • #25 — adopter quickstart + manifest patterns
  • #26 — OpenAPI converter regression fixtures (merged before this PR opened)
  • #27 — HTTP transport + bearer auth implementation
  • (this PR) — release polish

Version bump

Lockstep 0.3.00.4.0 across:

  • root package.json
  • packages/{core,sdk,scanner,openapi,cli}/package.json
  • apps/{mcp-server,demo-app,studio}/package.json
  • workspace dep ranges ^0.3.0^0.4.0
  • apps/mcp-server/src/server.ts SERVER_VERSION"0.4.0"
  • package-lock.json refreshed via npm install --package-lock-only
  • packages/openapi/README.md "method-based in v0.3.0" → "v0.4.0"

Release artifacts added

HTTP smoke wiring

  • scripts/http-mcp-smoke.mjs
    spawns the dist binary in HTTP mode on an ephemeral port and
    verifies:
    • server starts cleanly + stdout empty,
    • missing Authorization401,
    • wrong bearer → 401,
    • token in URL query string → 400 (no token in body),
    • unknown Origin403,
    • valid bearer + initialize200 with serverInfo {agentbridge, 0.4.0},
    • tools/list never leaks the token,
    • shutdown clean,
    • stderr never contains the token,
    • http mode without auth token fails closed at startup,
    • public bind without origin allowlist fails closed at
      startup.
  • package.json exposes npm run smoke:http.
  • scripts/external-adopter-smoke.mjs
    runs the HTTP smoke as a final step against the freshly-built
    dist inside the temp snapshot, so npm run smoke:external
    exercises both transports end-to-end.

CLI mcp-config

agentbridge mcp-config now prints an
"HTTP transport (experimental, v0.4.0 — opt-in)" block:

  • env-var recipe (placeholder token only, never logged),
  • generic hosted-client JSON config (transport: "streamable-http",
    url, Authorization: Bearer ${AGENTBRIDGE_HTTP_AUTH_TOKEN}
    placeholder),
  • safety reminder updated for outbound vs inbound allowlists,
    query-token rejection, public-bind fail-closed.

packages/cli/src/tests/cli.test.ts
asserts every new line plus a regex assertion that no
real-looking bearer token leaks to stdout.

Docs updated

Verification

npm run typecheck:clean        # green
npm test                       # 185/185 green
                                 (174 prior + 11 openapi-fixtures from PR #26)
npm run build                  # six packages OK; mcp-server bundle 40.3 KB ESM
npm run pack:dry-run           # six tarballs OK at 0.4.0
npm run smoke:http             # 13/13 ok against the built dist
                                 (token never logged)
npm run smoke:external         # PASS — fresh git archive, 42 scanner
                                 checks passed against demo, then
                                 stdio + HTTP smoke green.
node apps/mcp-server/dist/index.js < /dev/null
                               # exit 0
# stdio JSON-RPC subprocess smoke — serverInfo {agentbridge, 0.4.0};
#   stderr empty.
# CLI: version → 0.4.0; mcp-config prints stdio + HTTP blocks (no
#   real token); validate adopter manifests + openapi-regression
#   round-trip → ✓ valid.

Confirmations

  • stdio remains the default. No HTTP listener opens unless AGENTBRIDGE_TRANSPORT=http.
  • HTTP requires AGENTBRIDGE_HTTP_AUTH_TOKEN. Missing/short token fails closed at startup.
  • Tokens in URL query strings rejected with 400. Verified by HTTP smoke.
  • Origin allowlist exact-match; CORS never wildcard with credentials.
  • Public bind requires both auth and Origin allowlist or fails closed at startup.
  • Confirmation gate, origin pinning, target-origin allowlist, idempotency, audit redaction, simulated destructive demo actions — all unchanged.
  • Stdout hygiene preserved. stdio-hygiene.test.ts 3/3 + http-mcp-smoke asserts stdout is empty across the HTTP run.
  • Bearer token never in stdout, stderr, audit, or HTTP error bodies.
  • No npm publish, no git tag, no GitHub release.
  • Dependabot PRs untouched.
  • Codex PR docs: add adopter quickstart and manifest patterns #25 (already on main) untouched. Codex PR test(openapi): add converter regression fixtures #26 (merged before this PR opened) untouched apart from the strict additions to CHANGELOG.md and examples/README.md outlined above.

Test plan

  • npm run typecheck:clean green locally.
  • npm test — 185/185 green locally.
  • npm run build — six packages OK at 0.4.0.
  • npm run pack:dry-run — six tarballs OK at 0.4.0.
  • npm run smoke:http — 13/13 ok against the built dist.
  • npm run smoke:external — PASS against the just-committed branch.
  • CLI version / mcp-config / validate / generate openapi all green.
  • CI green on Node 20.x and 22.x.
  • Main CI green after merge.
  • release-check green on main.

Recommended next step

If all CI tracks are green, ask the maintainer for explicit
approval to publish @marmarlabs/agentbridge-*@0.4.0 via the
existing Trusted Publishing workflow. Do not publish without
explicit approval.

🤖 Generated with Claude Code

v0.4.0 implementation PR 3 — release polish + lockstep version
bump + HTTP smoke + CLI surface. Brings the v0.4.0 release line
into a publishable state. **Nothing is published; no git tag, no
GitHub release.** Publishing happens through the existing Trusted
Publishing workflow only after maintainer approval.

Refs #22.

What lands
----------

Versions (lockstep 0.3.0 → 0.4.0):
  - root package.json
  - packages/{core,sdk,scanner,openapi,cli}/package.json
  - apps/{mcp-server,demo-app,studio}/package.json
  - workspace dependency ranges ^0.3.0 → ^0.4.0
  - apps/mcp-server/src/server.ts: SERVER_VERSION → "0.4.0"
  - package-lock.json refreshed via `npm install --package-lock-only`
  - packages/openapi/README.md: "method-based in v0.3.0" → "v0.4.0"

Release artifacts:
  - docs/releases/v0.4.0.md — full release notes (summary,
    transport, security posture, env vars, stdio compat, Codex /
    Claude / generic notes, OpenAPI fixtures, adopter docs,
    migration, verification, publishing checklist, non-goals,
    PR links #23 / #24 / #25 / #26 / #27 / this, safety
    invariants explicitly preserved).
  - examples/http-client-config/README.md — local-dev recipe,
    curl smoke (missing/wrong/query-token/bad-origin/valid),
    generic hosted-MCP-client JSON shape, Codex / Claude note,
    public-bind caution. Placeholder token only; no secrets.
  - examples/README.md — adds http-client-config row without
    overwriting the PR #25/#26 rows.

Smoke / CI:
  - scripts/http-mcp-smoke.mjs — spawns the dist binary in HTTP
    mode on an ephemeral port and verifies:
      server starts cleanly + stdout empty,
      missing Authorization → 401,
      wrong bearer → 401,
      token in URL query string → 400 (no token in body),
      unknown Origin → 403,
      valid bearer + initialize → 200 with serverInfo
        {agentbridge, 0.4.0},
      tools/list never leaks the token,
      shutdown clean,
      stderr never contains the token,
      http mode without auth token fails closed at startup,
      public bind without origin allowlist fails closed at startup.
    Exit code = number of failures.
  - package.json: new `npm run smoke:http` script.
  - scripts/external-adopter-smoke.mjs runs the HTTP smoke as a
    final step against the freshly built dist inside the temp
    snapshot, so `npm run smoke:external` exercises both
    transports end-to-end.

CLI:
  - packages/cli/src/commands/mcp-config.ts prints an
    "HTTP transport (experimental, v0.4.0 — opt-in)" block with:
      env-var recipe (placeholder token only),
      generic hosted-client JSON config (transport:
        "streamable-http", url + Authorization header with
        ${AGENTBRIDGE_HTTP_AUTH_TOKEN} placeholder),
      safety reminder updated for outbound vs inbound
        allowlists, query-token rejection, public-bind fail-
        closed.
  - packages/cli/src/tests/cli.test.ts asserts every new line
    plus a regex assertion that no real-looking bearer token
    leaks to stdout.

Docs:
  - README.md: status block to "v0.4.0 release-prepared on
    `release/v0.4.0-http-polish`; not yet on npm"; HTTP roadmap
    bullet updated; release-notes pointer.
  - AGENTS.md: current-state block updated with PRs #23#27 +
    this PR; HTTP opt-in note.
  - CLAUDE.md: production/v1.0 references list adds the v0.4.0
    release-notes file.
  - docs/roadmap.md: v0.4.0 line marked release-prepared with
    file-path commitments; remaining gaps spelled out.
  - docs/v1-readiness.md: criteria #8 and #9 from "design
    complete" → "implemented opt-in in v0.4.0"; status block +
    transport surface row updated.
  - docs/threat-model.md: T14 rewritten with concrete v0.4.0
    mitigations (bearer auth, no query tokens, exact Origin
    match, loopback bind, public-bind fail-closed, stdout
    hygiene preserved) and explicit remaining gaps (OAuth
    resource server, token rotation, scopes, caller-identity
    propagation, deployment guides).
  - docs/security-configuration.md (already v0.4.0-tone in PR
    #27); no further changes required here.
  - docs/mcp-client-setup.md (already covers experimental HTTP
    transport in PR #27); no further changes required here.
  - apps/mcp-server/README.md: opening sentence + status block
    refreshed to mention default stdio + opt-in HTTP.
  - apps/mcp-server/src/transports/README.md: PR 3 marked
    landed with file-path commitments.
  - CHANGELOG.md: Unreleased content moved into a v0.4.0 entry
    with full Added/Changed/Compatibility breakdown; previous
    Unreleased docs lines folded into v0.4.0 since they ship
    in the same release line.

Verification (locally on the working tree)
------------------------------------------

  npm run typecheck:clean      → green
  npm test                     → 185/185 green (174 prior + 11
                                 openapi-fixtures from PR #26)
  npm run build                → six packages OK; mcp-server
                                 bundle 40.3 KB ESM
  npm run pack:dry-run         → six tarballs OK at 0.4.0
  npm run smoke:http           → 13/13 ok against the built dist
                                 (token never logged)
  node apps/mcp-server/dist/index.js < /dev/null
                               → exit 0; serverInfo
                                 {agentbridge, 0.4.0}; stderr
                                 empty.
  node packages/cli/dist/bin.js version       → 0.4.0
  node packages/cli/dist/bin.js mcp-config    → prints stdio +
                                                  HTTP blocks;
                                                  no real token.
  node packages/cli/dist/bin.js validate
    examples/adopter-quickstart/manifest.basic.json
    → ✓ valid
  node packages/cli/dist/bin.js validate
    examples/adopter-quickstart/manifest.production-shaped.json
    → ✓ valid
  node packages/cli/dist/bin.js generate openapi
    examples/openapi-regression/catalog-regression.openapi.json
    --out /tmp/agentbridge.openapi-regression.generated.json
    && validate /tmp/agentbridge.openapi-regression.generated.json
    → 8 actions; ✓ valid
  npm run smoke:external      → green (run after this commit
                                 since the script snapshots
                                 HEAD; results inline in the
                                 PR description).

Confirmations
-------------

- ✅ stdio remains the default. No HTTP listener opens unless
  AGENTBRIDGE_TRANSPORT=http.
- ✅ HTTP requires AGENTBRIDGE_HTTP_AUTH_TOKEN; missing/short
  token fails closed at startup.
- ✅ Tokens in URL query strings rejected with 400.
- ✅ Origin allowlist exact-match; CORS never wildcard with
  credentials.
- ✅ Public bind requires both auth and Origin allowlist or
  fails closed at startup.
- ✅ Confirmation gate, origin pinning, target-origin
  allowlist, idempotency, audit redaction, simulated
  destructive demo actions — all unchanged.
- ✅ Stdout hygiene preserved (stdio-hygiene 3/3 + http-mcp-smoke
  asserts stdout empty across the run).
- ✅ Bearer token never in stdout, stderr, audit, or HTTP error
  bodies.
- ✅ No npm publish, no git tag, no GitHub release.
- ✅ Dependabot PRs untouched.
- ✅ Codex PR #25 (already on main) and PR #26 (merged before
  this PR opened) untouched; no edits to CHANGELOG.md beyond
  moving the Unreleased section into the v0.4.0 entry, no edits
  to examples/README.md beyond appending the
  http-client-config row.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@marmar9615-cloud marmar9615-cloud merged commit 2e74516 into main Apr 28, 2026
2 checks passed
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b69452424c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


out.write(`${c.dim("Generic hosted-MCP-client config (adapt to your client):")}\n`);
out.write(indentBlock(JSON.stringify(httpClientConfig, null, 2)) + "\n");
out.write(` ${c.dim("# Resolve ${AGENTBRIDGE_HTTP_AUTH_TOKEN} via your client's secrets manager — never commit the literal token.")}\n\n`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Escape env-var placeholder in mcp-config output

The string passed to out.write interpolates ${AGENTBRIDGE_HTTP_AUTH_TOKEN} as a JavaScript identifier, but that variable is not defined in this module. As a result, running agentbridge mcp-config throws a ReferenceError at runtime before the command finishes, so users cannot get the config snippet. Print the placeholder literally (for example, by escaping $) instead of interpolating it.

Useful? React with 👍 / 👎.

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