UNPKG

@aashari/boilerplate-mcp-server

Version:

TypeScript MCP server boilerplate with STDIO and HTTP transport support, CLI tools, and extensible architecture

307 lines (209 loc) 7.68 kB
# MCP Modernization + Release Runbook ## Purpose This runbook documents the exact modernization + release approach used in this repository so other MCP servers can follow the same pattern with predictable outcomes. Scope covered: - Baseline audit (history, diffs, dependencies, CI) - Streamable HTTP transport hardening - Tool input/output contract standardization - Inspector-based validation - Semantic-release driven publishing --- ## Case Study Window (This Repo) Reference range analyzed: - From: `v3.0.0` (`fadd464`) - To: `HEAD` (`08f8a02`) Key commits: - `615b373` `feat: modernize HTTP transport and standardize MCP tool contracts` - `287cb4c` `chore(release): 3.1.0 [skip ci]` - `08f8a02` `docs: sync README and security guidance with current tooling` ### File-Level Change Summary (`v3.0.0..HEAD`) - `.releaserc.json` - `CHANGELOG.md` - `README.md` - `SECURITY.md` - `package-lock.json` - `package.json` - `src/controllers/ipaddress.controller.ts` - `src/index.ts` - `src/tools/ipaddress-link.tool.ts` - `src/types/common.types.ts` - `src/utils/constants.util.ts` - `src/utils/error-handler.util.ts` High-impact deltas: - `src/index.ts`: moved HTTP handling to session-aware streamable transport flow. - `src/tools/ipaddress-link.tool.ts`: aligned input schema with `ip_get_details`, standardized output to `text` + `resource_link`. - `src/controllers/ipaddress.controller.ts` + `src/types/common.types.ts`: exposed canonical `resolvedIp` to avoid parsing rendered output. - `package.json` + `package-lock.json`: dependency upgrades and script surface simplification. - `.releaserc.json`: added `src/utils/constants.util.ts` to git release assets to prevent version drift. --- ## Phase 1: Baseline Audit ### 1.1 Capture release baseline ```bash git tag --sort=-v:refname | head -n 10 git log --oneline --decorate vX.Y.Z..HEAD git diff --name-status vX.Y.Z..HEAD git diff --stat vX.Y.Z..HEAD ``` ### 1.2 Validate release pipeline wiring Check: - `.releaserc.json` - `.github/workflows/ci-semantic-release.yml` - `package.json` `engines`, scripts, dependencies Release prerequisites: - Conventional commits - Semantic-release workflow on push to `main` - OIDC trusted publishing (no `NPM_TOKEN` required) --- ## Phase 2: Modernize Streamable HTTP Transport ## Problem Pattern Stateless `StreamableHTTPServerTransport` reuse across requests causes failures after `initialize`. ## Correct Pattern Use stateful session management: - Create a transport on initialize - Generate `Mcp-Session-Id` - Store per-session `{ server, transport }` - Route POST/GET/DELETE by session - Cleanup on session close + process shutdown ## Implementation Checklist - Add session map keyed by `Mcp-Session-Id` - Validate initialize requests with `isInitializeRequest` - Reject non-initialize requests without session header - Implement: - `POST /mcp` for initialize + rpc - `GET /mcp` for SSE stream channel if used - `DELETE /mcp` for session termination - Add graceful shutdown over all sessions --- ## Phase 3: Standardize Tool Contracts Target rule for related tools: - Same input schema unless there is a strong functional reason to diverge. - Same base output shape for primary payload. - Additive behavior only where required (e.g., extra link item). ## Applied Pattern For `ip_get_details` and `ip_get_details_link`: - Input parity: - `ipAddress` - `includeExtendedData` - `useHttps` - `jq` - `outputFormat` - Output parity: - First content block is always `text` from the same toon/json renderer. - Link tool extension: - Second block is `resource_link` (`ip://<resolved-ip>`). ## Critical anti-pattern to avoid Do not parse rendered text (regex on TOON/JSON output) to recover structured fields. Instead: - expose canonical data from controller/service boundary (`resolvedIp`) and consume that. --- ## Phase 4: Test Matrix (Required) ### 4.1 Static quality gates ```bash npm run lint npm run build npm test -- --runInBand ``` ### 4.2 Streamable HTTP protocol flow test (curl) Required sequence: 1. `initialize` 2. `notifications/initialized` 3. `tools/list` 4. `tools/call` Assertions: - `initialize` -> `200`, has `mcp-session-id` - `notifications/initialized` -> `202` - `tools/list` -> `200` - `tools/call` -> `200` ### 4.3 SDK client compatibility test Use official transport: - `StreamableHTTPClientTransport` - `Client` from MCP TS SDK Assertions: - `connect()` succeeds - `tools/list` succeeds - representative `tools/call` succeeds ### 4.4 Inspector validation - CLI check: ```bash npx @modelcontextprotocol/inspector --cli "http://127.0.0.1:PORT/mcp" --transport http --method tools/list ``` - UI check via proxy token URL. For remote access: - `HOST=0.0.0.0` - `ALLOWED_ORIGINS` includes remote UI origin - set `MCP_PROXY_FULL_ADDRESS` to reachable host:port Security note: keep auth enabled (`MCP_PROXY_AUTH_TOKEN`), do not use `DANGEROUSLY_OMIT_AUTH`. --- ## Phase 5: Semantic Release Procedure ### 5.1 Pre-release checks ```bash git status --short npm run lint && npm run build && npm test -- --runInBand ``` ### 5.2 Commit strategy Use conventional commits: - `fix:` -> patch - `feat:` -> minor - `feat!:` or `BREAKING CHANGE:` -> major ### 5.3 Push and monitor ```bash git push origin main gh run list --repo <owner>/<repo> --limit 5 gh run watch <run-id> --repo <owner>/<repo> ``` ### 5.4 Verify artifacts ```bash git fetch --tags origin git tag --sort=-v:refname | head gh release list --repo <owner>/<repo> --limit 5 npm view <package-name> version ``` --- ## Release Config Guardrails ### Guardrail 1: Keep version files aligned If custom prepare scripts update files, ensure `@semantic-release/git` assets include them. In this repo: - `scripts/update-version.js` updates `src/utils/constants.util.ts` - therefore `src/utils/constants.util.ts` must be in `.releaserc.json` git assets. ### Guardrail 2: Avoid script sprawl Keep `package.json` scripts minimal and operationally relevant: - build/lint/test/format - core run paths (`cli`, `mcp:stdio`, `mcp:http`, `mcp:inspect`) Remove duplicate aliases that do not add behavior. ### Guardrail 3: Update active docs only When behavior changes, update: - `README.md` - `SECURITY.md` - active setup docs Do not rewrite historical/audit snapshots unless they claim current state. --- ## Reusable Execution Checklist - [ ] Identify release baseline tag and commit window - [ ] Review commit history + per-file diff stats - [ ] Validate semantic-release + CI workflow config - [ ] Modernize streamable HTTP transport to session-safe pattern - [ ] Standardize related tool input/output contracts - [ ] Remove output parsing hacks (regex/content scraping) - [ ] Run lint/build/tests - [ ] Run curl protocol flow tests - [ ] Run official SDK client tests - [ ] Run Inspector CLI + UI tests - [ ] Commit with conventional commit type - [ ] Push to `main` - [ ] Watch semantic-release workflow to completion - [ ] Verify git tag, GitHub release, npm version - [ ] Sync active docs with final behavior --- ## Appendix: Commands Used in This Repo ```bash # History/diff tracing git log --oneline --decorate v3.0.0..HEAD git diff --name-status v3.0.0..HEAD git diff --stat v3.0.0..HEAD # Semantic-release dry check (local repo URL fallback) npx semantic-release --dry-run --no-ci --branches main \ --repository-url file:///absolute/path/to/repo \ --plugins @semantic-release/commit-analyzer @semantic-release/release-notes-generator # Inspector CLI against streamable HTTP npx @modelcontextprotocol/inspector --cli "http://127.0.0.1:3330/mcp" --transport http --method tools/list ```