Skip to content

Contributing and Releases

Chenglei Yuan edited this page Jun 4, 2026 · 1 revision

Contributing and Releases

How to set up a development environment, run the tests, drive the proxy by hand, and how releases are cut. For the code internals, see Architecture, Bridge Internals, and OAuth2 Internals.

Project layout

src/
  index.ts              entry point / startup orchestration
  config.ts             zod schema + env overrides + load-time validation
  security.ts           loopback + cleartext-HTTP policy
  log.ts                pino → stderr with redaction
  stdio.ts              newline-delimited JSON-RPC codec
  bridge.ts             message loop (HTTP/SSE forwarding)
  oauth2/
    tokenManager.ts     access-token cache + refresh + dedup
    factory.ts          grant selection + cache wiring
    discovery.ts        RFC 9728 / RFC 8414 / OIDC discovery
    interactive.ts      PKCE + callback server + browser open
    tokenCache.ts       AES-256-GCM refresh-token cache
    http.ts             token-endpoint client + parsing
    grants/
      types.ts          Grant interface
      clientCredentials.ts
      authorizationCode.ts
      refreshToken.ts
test/                   vitest unit + integration suites

Dev setup

npm install
npm run build       # compile TS → dist/
npm run dev         # tsx watch (rebuild on change)
npm run dev:once    # one-shot tsx run
npm start           # run the compiled dist/index.js

Requires Node.js 20+. Runtime deps: pino, undici, zod.

npm scripts

Script What it does
npm run build tsc — compile to dist/.
npm run dev tsx watch — rebuild on change.
npm run dev:once One-shot tsx run.
npm start Run dist/index.js.
npm test vitest run — unit + integration.
npm run test:watch vitest in watch mode.
npm run lint eslint --ext .ts.
npm run format prettier.

Note: the two reliably validated build/test commands are npm test (vitest) and npm run build (tsc). Run both before opening a PR.

Test strategy

Tests live in test/ and use vitest. They cover:

  • Unit suitessecurity, config, tokenManager, each grant (clientCredentials, authorizationCode, refreshToken), discovery, interactive, and the tokenCache.
  • Integrationbridge.integration.test.ts spins up a mock OAuth2 token endpoint and a mock MCP upstream HTTP server in-process, then drives the real Bridge through PassThrough streams. It exercises the Bearer header, session-id capture, SSE responses, the server-notification stream, and the 401-invalidate-and-retry path — all with no real network.

When adding behavior, prefer extending the in-process mocks so tests stay hermetic.

Driving the proxy by hand

Run the compiled binary and paste JSON-RPC lines on stdin:

UPSTREAM_URL=https://mcp.example.com/mcp \
OAUTH2_GRANT=authorization_code \
OAUTH2_CLIENT_ID=<your-client-id> \
LOG_LEVEL=debug \
  node dist/index.js
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"cli","version":"0"}}}

stdout shows the upstream response; stderr shows pino logs (secrets redacted).

Or use the official MCP inspector:

npx @modelcontextprotocol/inspector \
  --command node \
  --args dist/index.js \
  -e UPSTREAM_URL=https://mcp.example.com/mcp \
  -e OAUTH2_GRANT=authorization_code \
  -e OAUTH2_CLIENT_ID=<your-client-id>

Releases

Releases are fully automated via release-please and Conventional Commits:

  1. Every PR title must follow Conventional Commits (feat:, fix:, docs:, chore:, …); a PR Title Lint check enforces this.
  2. PRs are squash-merged, so the PR title becomes the main commit message.
  3. On each push to main, release-please opens/updates a Release PR that bumps package.json and updates CHANGELOG.md.
  4. Merging the Release PR creates a vX.Y.Z tag and GitHub Release.
  5. A Publish to npm workflow fires on the new tag and publishes via npm OIDC trusted publishing — no NPM_TOKEN secret is used.

Bump rules (pre-1.0, bump-minor-pre-major: true)

Commit prefix Bump
fix: patch
feat: minor
feat!: / BREAKING CHANGE: footer minor (until 1.0.0, then major)
docs: / chore: / refactor: / test: / ci: / build: / perf: no release

One-time repo settings

  • Default merge strategy: Squash and merge.
  • Settings → Actions → General → Allow GitHub Actions to create and approve pull requests.

Contributing checklist

  • Use a Conventional Commit PR title.
  • Add or extend tests (keep them in-process / hermetic).
  • Run npm test and npm run build locally.
  • Keep secrets out of logs and config files; never log raw tokens.

Clone this wiki locally