All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.9.0 - 2026-08-10
Cross-field argument validation now reads the same on every tool that has it. Tool inventory is unchanged at 171 and tools/list output is byte-identical to 0.8.0, so no client needs to re-sync schemas. The error text a client sees for these ten tools does change; anything matching on the old strings needs updating.
- Render schema validation failures as a readable sentence instead of a serialized issue array.
ZodError.messageis a JSON dump, and tools that validated withsuperRefinesurfaced it verbatim, so a caller gotTool "create_api_key" failed: [\n {\n "code": "custom", ...where the useful part — the field and what it wants — was buried in escaped noise. Issues are now flattened tofield: message, joined with;. - Distinguish a bad argument from a broken tool. Validation failures now read
Invalid arguments for "<tool>": <what is wrong>; genuine tool failures keepTool "<tool>" failed: <reason>. Previously both used the failure wording.
- Route every cross-field validation rule through one pattern: the raw shape stays the registered
inputSchema, and a siblingsuperRefineschema is parsed inside the handler. Ten tools were split across three behaviours before this —create_config,update_integration_workspaces,create_prompt_label,create_mcp_integration,create_prompt, andmigrate_promptreturned hand-written strings from manualifchecks;get_logandcreate_scim_workspace_mappingregistered the refined schema directly and answered with the SDK's unenvelopedMCP error -32602text; onlycreate_api_keyused the pattern now standard. Registering the refined schema carried no benefit, since asuperRefinehas no JSON Schema representation and never reachedtools/list.
0.8.0 - 2026-08-09
Code-health release from a full-application review across security, performance, quality, and testing. No tools were added or removed; the inventory stays at 171. Security review found no exploitable issues. The tracked findings, including the ones deliberately not acted on, are recorded as Phase 6 in ROADMAP.md.
- Cover the Clerk authentication success path, which previously had no test anywhere: the suite now mints a real RSA keypair, signs a real JWT, serves a matching JWKS, and asserts the middleware admits the request with a correctly populated principal. The former placeholder asserted nothing while claiming the contract was covered elsewhere.
- Drive
BaseServicethrough real 4xx JSON and 5xx non-JSON upstream error bodies, and exercise the unauthenticated public-catalog path including an assertion that no API key header is sent. - Add behavioural coverage for nine API/virtual key tool callbacks and five user-invite tool callbacks, plus representative analytics callbacks and a table walk that pins every generic-graph registration to its service method.
- Add unicode, null-byte, RTL-override, and script-like string coverage through path-segment encoding and free-text parameters, and cover the 413 payload-too-large response.
- Add
jsonResult()and route all 173 tool result envelopes through it instead of hand-rolling the same JSON block per handler, and drop the stringify-then-reparse round-trip that rebuiltstructuredContentfrom text already serialized from the same object. - Register the eight generic graph analytics tools from a table rather than eight identical bodies, and extract virtual-key and API-key response formatters in line with the convention every sibling tool module already followed.
- Split
createHttpAppRuntimeinto pure wiring plus nine named route-handler factories. Status codes, error bodies, headers, log lines, middleware order, and the session reservation lifecycle are unchanged. - Document tool-domain scoping as the primary lever on client context cost, not only an access-control setting.
- Validate
user_idas a UUID onget_workspace_member,update_workspace_member, andremove_workspace_member. Previously onlyadd_workspace_memberdid, so a malformed ID on the other three reached the Portkey API and surfaced as a raw upstream error instead of an actionable local one. - Return a real success payload from
delete_collectionanddelete_configwhen Portkey answers with204 No Content.BaseServicefabricated an empty object typed as a full response, sosuccessread back asundefinedand was dropped from the result entirely. - Describe the SCIM
pageparameter as zero-based. Every other list tool takes a 1-basedcurrent_page, and nothing flagged the difference, so a client generalizing from the other tools would mis-paginate.
0.7.0 - 2026-08-09
- Resume compatibility and API-coverage development with 15 current Portkey tools: organisation guardrail defaults and directional workspace exclusions; single-log reads and log-export field restrictions; SCIM group search and workspace-mapping CRUD; MCP server connection listing/disconnect; and public model-pricing lookup. The inventory now contains 171 tools.
- Cover current integration schemas for Secret Reference mappings, pricing adjustments, default-provider creation, global workspace access/overrides, custom and fine-tuned models, per-model headers/hosts, and static model pricing. MCP integrations now expose Secret Reference mappings as well.
- Add contract-first regression tests for every new service path and tool payload plus a tool-quality gate for decision-oriented descriptions, documented fields, titles, and accurate MCP annotations.
- Add a Glama TDQS-aligned release preflight that inspects the built MCP
tools/listoutput for description hard gates, parameter documentation, output schemas, annotations, and selection guidance; run it in both local and hosted CI. - Add
docs/PRISMA_AIRS_INTEROPERABILITY.mdwith the supported Portkey/Prisma AIRS coexistence model and criteria for a future native Prisma AIRS adapter.
- Replace the stale post-acquisition maintenance warning with active compatibility status. Portkey remains the supported API contract; Prisma AIRS/Strata Cloud Manager is documented as a separate, non-drop-in management surface.
- Normalize current integration model/workspace list response keys while retaining the MCP result shape, and route public model-pricing reads through Portkey's unauthenticated non-
/v1catalog origin. - Mark organisation-governance, Logs Export, and SCIM tools as enterprise-gated in MCP descriptions, including the documented organisation and log-export API-key scopes.
- Synchronize npm, MCP Registry, and LobeHub release metadata; package the local documentation linked from the README; document Glama's tag-driven refresh; and allow the credentialed staging smoke suite to run in CI.
- Follow LobeHub's claimed-listing workflow: regenerate every MCP capability array and use
plugin updatefor new marketplace versions, retaining the former publish script as an alias.
- Accept SCIM mapping/group page
0as Portkey's first page, explain that a group name can pre-create the Portkey SCIM group, and clarify that deleting a workspace mapping leaves already provisioned members in place.
0.6.3 - 2026-08-04
Security patch for two advisories published against transitive dependencies of @modelcontextprotocol/sdk shortly after 0.6.2 was cut. No Portkey Admin API or MCP tool-surface changes; the 156-tool inventory is unchanged.
- Upgrade transitive
fast-urito 3.1.5, closing a high-severity host-confusion advisory triggered by a backslash authority introducer. Reached throughajv. This is a distinct bypass from thefast-uriissue patched in 0.6.1. - Upgrade transitive
honoto 4.13.0, closing a medium-severity ReDoS in the CORS middleware via theAccess-Control-Request-Headersheader. Reached through@hono/node-serverand the SDK directly.
Both are lockfile-only resolution bumps; no declared dependency ranges changed. GitHub Dependabot reports no remaining alerts.
0.6.2 - 2026-08-04
Maintenance and dependency-security patch. No Portkey Admin API or MCP tool-surface changes; the 156-tool inventory is unchanged.
- Upgrade transitive
ip-addressto 10.4.0, closing two medium advisories reached throughexpress-rate-limit. A CIDR suffix on a parsed address suppressed special-use classification, and IPv4-mapped and NAT64 IPv6 addresses were misclassified; both allowed SSRF and trust-boundary checks to be bypassed. GitHub Dependabot reports no remaining alerts.
- Update non-major npm dependencies:
@biomejs/biome2.5.6,express-rate-limit8.6.1,jose6.2.7,knip6.29.0, andredis6.2.0. - Move the CI Redis service image to
redis:8.8-alpine. - Bump the pinned
packageManagertonpm@12.0.2. This is a build-tooling pin only and does not affect the published package; npm 12 requires Node^22.22.2 || ^24.15.0 || >=26, which the Node 24 toolchain used in CI and the Docker image already satisfies.
- Drop the unused
BaseServiceandvalidateUrlre-exports from the services barrel. Neither was ever imported through it, and knip 6.29 flags them. Both remain exported fromsrc/services/base.service.ts, where every consumer already imports them.
0.6.1 - 2026-07-28
Maintenance and dependency-security patch. No Portkey Admin API or MCP tool-surface changes; the 156-tool inventory is unchanged.
- Upgrade
@modelcontextprotocol/sdkto 1.30.0, allowing the patched@hono/node-server2.0.12 and closing the Windows encoded-backslash path-traversal advisory (GHSA-frvp-7c67-39w9). - Upgrade transitive
fast-urito 3.1.4, closing the host-confusion advisory (GHSA-v2hh-gcrm-f6hx). GitHub Dependabot andnpm auditreport no remaining vulnerabilities.
- Resolve the verified npm tarball artifact to an absolute path before publishing, preventing npm from misinterpreting the relative tarball path as a GitHub repository shorthand.
- Update non-major npm dependencies and pinned GitHub Actions, including
actions/setup-node7.0.0 andactions/checkout7.0.1.
0.6.0 - 2026-07-20
Security-hardening release. Remediates all eight findings (two high, four medium, two low) from the 2026-07-20 best-practices review; each fix ships with regression tests or configuration assertions. See security_best_practices_report.md for the full evidence and verification log. No Portkey Admin API tool surface changes — the 156-tool inventory is unchanged.
Several changes are breaking for HTTP/hosted deployments and require operator action:
- Production Redis (
MCP_EVENT_STORE=redis/RATE_LIMIT_STORE=redis) now requires arediss://URL on non-loopback hosts. - Redis replay now requires
MCP_EVENT_ENCRYPTION_KEY(base64 32-byte AES key; generate withopenssl rand -base64 32). - Clerk mode now requires at least one authorization policy (
CLERK_ALLOWED_SUBJECTS,CLERK_ALLOWED_ORGANIZATION_IDS,CLERK_ALLOWED_ROLES, orCLERK_REQUIRED_PERMISSIONS); a valid JWT alone is no longer sufficient. - Production HTTP must choose a rate-limit topology explicitly:
RATE_LIMIT_STORE=redis, orRATE_LIMIT_SINGLE_PROCESS=truefor a single long-lived process. - Outbound Portkey calls are HTTPS-only by default; a plaintext self-hosted gateway now needs
PORTKEY_ALLOW_INSECURE_HTTP=truein addition toPORTKEY_ALLOW_PRIVATE_BASE_URL. MCP_EVENT_TTL_SECONDSdefault drops from3600to300.
- SEC-001 (High):
PORTKEY_TOOL_DOMAINS/MCP_TOOL_DOMAINSis now a hard server-side allowlist. The HTTP?tools=query can only narrow it; a requested domain outside the configured set is rejected instead of silently overriding it, closing an authorization bypass where a caller could re-enable excluded key/user/secret mutation tools. - SEC-002 (High): Clerk mode now authorizes the verified subject rather than granting the shared
PORTKEY_API_KEYto any valid token. It requires at least one explicit subject/organization/role/permission policy, evaluates every configured constraint, and attaches a normalized principal to the request. Breaking: existing Clerk deployments must add a policy. - SEC-003 (Medium): Sessions, in-memory and Redis replay events, per-stream leases, and replay cursors are bound to an opaque principal digest and equality-checked on every POST/GET/DELETE/replay. Raw session and event IDs are no longer logged; logs use capability fingerprints.
- SEC-004 (Medium): Credentialed Portkey requests use
redirect: "manual"sox-portkey-api-keycan never follow a redirect to another origin, and default to HTTPS. Breaking: plaintext private gateways require the newPORTKEY_ALLOW_INSECURE_HTTP=trueopt-in alongsidePORTKEY_ALLOW_PRIVATE_BASE_URL. - SEC-005 (Medium): Redis replay payloads are encrypted with AES-256-GCM using
MCP_EVENT_ENCRYPTION_KEY, non-loopback production Redis requiresrediss://, events carry an enforced owner, and default retention drops to 300 seconds. Breaking:redis://in production and a missing encryption key are now rejected. - SEC-006 (Medium): Renovate enforces a repository-wide seven-day minimum release age and no longer automerges lockfile maintenance or devDependency updates. The release pipeline packages the tarball in a non-OIDC job and publishes only that verified artifact.
- SEC-007 (Low): Added a distributed rate limiter — an atomic pre-authentication bucket keyed by normalized trusted IP and a post-authentication bucket keyed by principal plus IP, both Redis-backed and IPv6-subnet-normalized. Breaking: production must set
RATE_LIMIT_STORE=redisorRATE_LIMIT_SINGLE_PROCESS=true; the process-local limiter remains only as defense in depth. - SEC-008 (Low): The runtime container removes npm, npx, and npm's global module tree after installing production dependencies, dropping the bundled
tar/undiciadvisories from the image.
PORTKEY_ALLOW_INSECURE_HTTP,MCP_EVENT_ENCRYPTION_KEY,RATE_LIMIT_STORE,RATE_LIMIT_SINGLE_PROCESS,RATE_LIMIT_REDIS_URL,RATE_LIMIT_REDIS_KEY_PREFIX, and the Clerk authorization variables (CLERK_ALLOWED_SUBJECTS,CLERK_ALLOWED_ORGANIZATION_IDS,CLERK_ALLOWED_ROLES,CLERK_REQUIRED_PERMISSIONS) — documented in the README env-var table,.env.example, anddocs/VERCEL_DEPLOYMENT.md.express-rate-limit(8.x) promoted to a direct dependency for the defense-in-depth Express limiter.security_best_practices_report.md— the full remediation report with per-finding evidence, mitigations, and the verification matrix (npm audit, Trivy, Gitleaks, Semgrep, Zizmor, Actionlint, live Redis integration).
MCP_EVENT_TTL_SECONDSdefault3600→300, shortening the window in which replay data lives at rest.RATE_LIMIT_MAX_BUCKETSnow applies only in explicit memory mode.- The Vercel guide,
.env.example, and Dockerfile document the requiredrediss://, replay encryption key, and explicit rate-limit topology for production.
0.5.0 - 2026-07-14
- Type-check the test suite in local and hosted CI, align Node type definitions with the Node 24 runtime, and pin the expected npm version through
packageManager. - Add stateless
GET /mcpredelivery fromLast-Event-ID, including detached completion when a client disconnects before an in-flight POST result is ready. - Add
rotate_api_keyand five Secret Reference CRUD tools, plus documented-response fixtures, contracts, and a safe disposable live-fixture recorder.
- Upgrade to node-redis 6.1 and TypeScript 7.0 while preserving the Redis event store's RESP2, timeout, and keepalive behavior.
- Keep the stateless event store opt-in (
offby default);memoryenables single-instance replay andredisenables cross-instance replay. - Require integer
current_pageandpage_sizevalues across all paginated tools.
- Pin the MCP Registry publisher to v1.7.9 and verify its official SHA-256 checksum before executing it in the OIDC-enabled release job.
- Harden unauthenticated loopback Host validation for IPv4 and bracketed IPv6, including rejection of malformed IPv6 authority suffixes.
- Use opaque replay cursors and per-stream memory/Redis leases so cursors cannot be guessed and concurrent replay connections cannot duplicate delivery.
- Run release CI and registry publishing against the requested tag during manual/automatic dispatches instead of implicitly checking out
main. - Normalize trailing slashes in
PORTKEY_BASE_URL, strictly validate integer environment settings, and apply the configured graceful-shutdown timeout consistently. - Accept post-initialization MCP requests without a protocol header by using negotiated/backwards-compatible behavior, while continuing to reject unsupported or mismatched versions.
- Return controlled JSON for malformed request bodies instead of Express's default HTML error response.
- Restore the missing 0.4.1 changelog boundary and clearly label the June audit and completed roadmap as historical snapshots.
0.4.2 - 2026-07-02
migrate_prompt's 0.4.1 description enumerated only two of the threeactionreturn values; the common re-run case returnsunchanged(prompt found, content identical, no new version created). The description now covers all three outcomes plus themessagefield.- The LobeHub manifest generator inherited the caller's environment, so a stray
PORTKEY_TOOL_DOMAINS/MCP_TOOL_DOMAINSexport made it silently write a truncated manifest (reproduced: 34 of 150 tools). It now strips both variables, refuses to write fewer tools than the manifest already has, and carries each tool'sannotationsthrough to the manifest (previously dropped). - Pin the actionlint bootstrap script in CI to a commit SHA — the tag-based raw URL was the one remaining mutable reference in the hardened workflows.
- Correct two claims in the 0.4.1 changelog entry (mirrored to its GitHub Release): the six tools carry the first hand-authored annotations, not the first annotations, and the manifest drift was 29 tool entries, not 34.
0.4.1 - 2026-07-02
- Rewrite the six lowest-scoring tool descriptions (Glama TDQS):
update_config,update_integration,create_integration,update_mcp_integration_capabilities,update_mcp_integration_workspaces, andmigrate_promptnow disclose side effects and reversibility, name sibling tools and where to source parameter values, and enumerate return fields. These six are also the first tools to carry explicit hand-authored MCP annotations (readOnlyHint/destructiveHint/idempotentHint/openWorldHint), overriding the operation-type-inferred annotations every tool has carried since 0.2.0.
- The LobeHub manifest (
lhm.plugin.json) had drifted from the server: 29 tool entries were out of date — the six rewritten descriptions plus 0.4.0's pagination schema changes, including alist_guardrailsschema still advertising apage_sizemaximum of 1000 that the server rejects at 100. The tools array is regenerated from the live server over MCPtools/list(newscripts/generate-lobehub-tools.mjs, wired intopublish:lobehubso it can't drift again), which also picks up the Enterprise-gating notes the server appends at registration. glama.jsonmaintainers listed the GitHub org instead of a username, which Glama's claim flow can't match; restoredscttbnsnso the org-hosted server page can be claimed.
0.4.0 - 2026-07-02
Maintenance release: dependency security patches, a Docker base-image CVE fix, and CI/repo hardening. Two breaking changes: the minimum Node.js version rises to 24, and page_size caps tighten on three list tools (callers passing values above 100 are now rejected at input validation). No other Portkey Admin API surface changes.
- Update transitive
honoto 4.12.27, closing five published advisories including GHSA-88fw-hqm2-52qc (CORS credential-reflection, CVSS 7.1). Bumptsxto 4.22.5 so its nestedesbuildclears GHSA-g7r4-m6w7-qqqr.npm audit: 0 vulnerabilities. - Bump the Docker base image from
node:24.12-alpinetonode:24.18-alpine, picking up the Node 24.17.0 LTS security release (CVE-2026-48618 TLS wildcard-hostname bypass, CVE-2026-48933 WebCrypto DoS). - Add
.dockerignoreso.env,.git, and local credentials never enter the Docker build context. - Harden CI: workflow-level least-privilege
permissionsblock, the optional staging secret scoped to the single smoke step that uses it, andactions/checkout/actions/setup-nodepinned to release commit SHAs (checkout moves v6 → v7). - Harden the release pipeline to zizmor-clean: job-scoped permissions replace the workflow-level
contents: write, checkouts stop persisting git credentials where jobs run dependency scripts, npm caching is off in the publish jobs, and the CI gate receives its one secret explicitly instead ofsecrets: inherit. CI gains anactionlintworkflow-lint job, PR dependency review, and per-branch concurrency; CodeQL default setup is enabled on the repo.
- LobeHub marketplace support:
lhm.plugin.jsonmanifest, apublish:lobehubnpm script, and a documented publish flow indocs/RELEASE.md; the README badge switched to the themedmcp-fullLobeHub badge. - Prerelease versions (any
-tag, e.g.0.5.0-rc.1) now publish to thercnpm dist-tag instead oflatest.
- Minimum Node.js version is now 24 (
engines.node: ">=24"). Node 20 reached end of life on 2026-04-30; the build target, CI, and the Docker image already ran Node 24. - Breaking: cap
page_sizeat 100 onlist_workspacesandget_user_stats, and alignlist_guardrailsdown from 1000 to 100, matching every other list tool. Requests with larger values are rejected by input validation instead of forwarded. - Correct the
update_configdescription — all routing/cache/retry fields are editable, not just name/status — and pointupdate_integrationat itsupdate_integration_models/update_integration_workspacessiblings. - Adopt the shared CodesWhat Renovate preset for dependency automation; refresh all in-range dependencies (helmet 8.2.0, jose 6.2.3, zod 4.4.3, typescript 6.0.3, biome 2.5.2 with config migration, knip 6.24.0, esbuild 0.28.1).
- README: animated 3D header icon; drop the typing-SVG banner.
- README's Docker HTTP example never set
MCP_TRANSPORT=http, so as documented it silently started the stdio server instead of the HTTP server it was configuring. - Repair
npm run test:http(scripts/test-mcp-http.sh): send the requiredMCP-Protocol-Versionheader after initialize, default tolocalhost(default host validation rejects127.0.0.1), and stop false-positiving on theerrorproperty inside tooloutputSchemas.
0.3.8 - 2026-06-18
Marketplace validation release for LobeHub and other MCP catalogs. No Portkey Admin API surface changes.
- Register a built-in
plan_portkey_admin_workflowMCP prompt so clients and catalogs can discover an invokable prompt; the prompt validates argument lengths, embeds the workflow guide as an MCP resource, and reminds clients to treat user task text as lower-priority context. - Register a static
portkey-admin://docs/workflow-guideMCP resource with safe usage guidance and assistant-priority annotations for discovery-first Portkey Admin workflows. - Add MCP e2e coverage for prompt/resource capabilities, listing, prompt rendering, resource reading, and no-key catalog inspection.
- Allow the shared MCP service factory to initialize without
PORTKEY_API_KEYso marketplaces can inspect server capabilities before users provide secrets. DirectPortkeyServiceconstruction and actual Admin API calls still require real credentials. - GitHub Releases now use the matching
CHANGELOG.mdversion section as the release body (with the auto-generated PR list appended), instead of auto-generated notes alone.
- Use LobeHub's lowercase
codeswhat-portkey-admin-mcpbadge slug so owner-claim scans match the marketplace page exactly.
0.3.7 - 2026-06-11
Security hardening, pagination params, compact tool responses, and a major test-coverage expansion from a four-domain code review. Tool-param additions are additive; no breaking API surface changes.
- Sanitize the caller-supplied
MCP-Protocol-Versionheader before echoing it in HTTP error responses — truncated to 64 chars and restricted to[A-Za-z0-9._-], closing an unvalidated-input reflection path. - Remove Redis configuration details from the unauthenticated
/auth/inforesponse to reduce infrastructure fingerprinting. - Send
Strict-Transport-Securityonly when TLS is enabled, instead of emitting HSTS on plain-HTTP responses. - Emit a startup warning when
ALLOWED_ORIGINS=*is combined withMCP_AUTH_MODE=none— wildcard CORS with no auth gate is a dangerous misconfiguration, now surfaced at boot rather than silently permitted. - Hash service-cache map keys with SHA-256 so plaintext API keys are never used as in-process cache identifiers.
- Route health checks through
BaseServiceso they receive the same SSRF URL validation and structured error parsing as every other upstream call (previously a bespoke fetch path bypassed both). create_api_keydescription now warns that the key secret is returned exactly once and will appear in MCP transcripts and LLM context — store it securely immediately.
- Pagination params on six list tools —
list_virtual_keys,list_configs,list_all_users,list_user_invites,list_mcp_server_capabilities, andlist_mcp_server_user_accessnow accept optionalcurrent_page/page_sizeinputs, forwarded to the Portkey Admin API; the two MCP-server lists also surfacehas_moreso truncated results are no longer indistinguishable from complete ones. - Cross-field validation for
create_api_key— the workspace key type now requiresworkspace_idat the Zod schema layer instead of failing inside the handler. - 140 new tests across 5 new test files: unit coverage for 13 previously untested tool modules, Clerk JWT auth mode,
DELETE /mcpand SSEGET /mcpsession endpoints, abort/timeout and upstream-error propagation paths, query-string and pagination edge cases, and contract schemas with live-recorded fixtures for workspaces and users. Total suite: 269 tests (253 unit/integration + 16 e2e).
- Compact JSON tool responses (~157 call sites) — tool responses no longer pretty-print with 2-space indent, reducing response token usage on every tool call.
- Lazy Redis import — the
redisclient module now loads only when the Redis event store is actually constructed, trimming cold-start weight when the event store isofformemory. create_integration/update_integrationpreserve empty strings — explicitly provided empty-string values (e.g.custom_host) are now sent to the API instead of being silently dropped by truthiness checks.migrate_prompt/promote_promptinternal prompt lookups now request a small page instead of a full listing.PORTKEY_BASE_URLvalidated once per service container instead of once per domain service, so misconfiguration fails fast with a single clear error.- HTTP transport repositioned as proof of concept — README and the Vercel guide now state there is no hosted version and stdio is the supported transport.
0.3.6 - 2026-06-05
Corrects the MCP Registry namespace case. No tool schema or API surface changes.
- Publish under
io.github.CodesWhat/portkey-admin-mcp, matching the exact GitHub organization login case, instead of the lowercasedio.github.codeswhatshipped in 0.3.5 — the registry's namespace authorization is case-sensitive and rejected the lowercase form with403.package.jsonmcpNameandserver.jsonnameupdated to match; the npm package name (portkey-admin-mcp) is unchanged.
0.3.5 - 2026-06-05
Moved the project to the CodesWhat organization following the s-b-e-n-s-o-n → scttbnsn GitHub handle rename, consolidating it alongside the other CodesWhat open-source projects. No tool schema or API surface changes.
- Repo moved to
github.com/CodesWhat/portkey-admin-mcp; MCP Registry namespace migrated fromio.github.s-b-e-n-s-o-n/portkey-admin-mcptoio.github.codeswhat/portkey-admin-mcp(server.jsonname,package.jsonmcpName, repository/homepage/bugs URLs). The old handle's registry namespace can no longer be verified, so it is retired. - The npm package name (
portkey-admin-mcp) is unchanged — existingnpx portkey-admin-mcpinstalls keep working — and the package now lives under thecodeswhatnpm org.
0.3.4 - 2026-06-05
Follow-up hardening release clearing the remaining low/medium items from the v0.3.3 audit (docs/audit-2026-06.md). No tool schema or API surface changes.
- Redact outbound request debug logs: log query-param keys only, never the composed URL, so identifiers in query values cannot leak into logs.
- Validate Redis event-store stream/event ids against
^[\w-]{1,128}$before key construction, preventing key injection via a malformedLast-Event-IDheader. Unknown/malformed ids resolve to "not found" instead of erroring.
- Gate the release workflow on the full CI suite:
release.ymlnow callsci.yml(made reusable viaworkflow_call) and both the GitHub Release and MCP Registry publish jobsneedit, so a broken tag can never ship.
tests/fixtures/manifest.jsonrecords fixture provenance (recordedAt, source, list);record:fixturesnow stamps it on every re-record, and the contract suite asserts it stays in sync withtests/fixtures/responses/.
0.3.3 - 2026-06-04
Maintenance and security release following the Palo Alto Networks acquisition of Portkey (completed 2026-05-29). The Portkey Admin API remains live and unchanged; this release hardens the HTTP transport, patches transitive CVEs, and marks the project as maintenance-only. No tool schema or API surface changes.
- Wire
Host-header validation into the HTTP transport forMCP_AUTH_MODE=nonedeployments, closing a DNS-rebinding gap where the existingisAllowedHostcheck was defined but never called. Authenticated (bearer/clerk) modes are unaffected. - Harden
PORTKEY_BASE_URLvalidation against SSRF: loopback, private (RFC-1918), CGNAT, and link-local hosts (including cloud metadata169.254.169.254) are now rejected by default. SetPORTKEY_ALLOW_PRIVATE_BASE_URL=trueto allow a self-hosted gateway on a private address. Internal DNS names remain allowed. - Patch transitive advisories via lockfile refresh (
fast-uri,hono,qs,ip-address/express-rate-limit).
- Return HTTP
404(not400) for requests against an unknown MCP session id, per the MCP spec, so clients re-initialize correctly. - Correct tool annotations for
run_prompt_completionandtest_mcp_server: these are side-effecting and no longer carryreadOnlyHint: true.
- The project is now in maintenance mode (security/dependency patches only) pending Palo Alto's post-acquisition Admin API roadmap. Added a status notice to the README and a full assessment under
docs/audit-2026-06.md. - Documented the previously-undocumented
PORTKEY_BASE_URLenvironment variable and the newPORTKEY_ALLOW_PRIVATE_BASE_URLopt-out. - Corrected the
ROADMAP.mdtool count (151 → 150, arithmetic fix) and marked the roadmap as maintenance-mode.
0.3.2 - 2026-04-16
Follow-up description-quality pass targeting the 13 tools that Glama's TDQS rubric left in the B-tier band. Adds a reproducible scoring harness under docs/glama-score/ and scripts/glama-score/ so future audits are one command. No behavior, schema, or API surface changes.
- Tightened 13 tool descriptions to A-tier TDQS (≥3.5):
cancel_log_export,create_config,get_guardrail,update_guardrail,list_prompt_partials,publish_partial,publish_prompt,resend_user_invite,update_api_key,update_integration_workspaces,update_prompt_label,update_usage_limit,update_workspace. Each gains one named-sibling disambiguation clause (unlike X which Y) plus one behavioral clause covering immediacy, scope, or immutability. - Rubric-based scoring of all 150 current descriptions against the reverse-engineered Glama TDQS rubric puts the server at mean 3.81, 150/150 at A-tier (up from baseline mean 3.14 at v1.0.0 with 61 C-tier tools).
docs/glama-score/— audit artifacts: the v1.0.0 Glama scan (scores.json,scores.csv), per-dimension justifications bucketed by score, the rewrite plan with per-tool checklist, and the post-fix re-score (current-scores.json,diff.json).scripts/glama-score/— reproducible audit tooling:extract-current.mjspulls every(name, description)pair fromsrc/tools/*.tools.ts,score-tools.mjsre-scores via the Anthropic Messages API with the rubric prompt-cached, anddiff-scores.mjsemits the baseline-vs-current delta.
0.3.1 - 2026-04-16
Maintenance release. Description-quality pass across every MCP tool and a routine patch-level dependency refresh. No behavior, schema, or API surface changes.
- All 150 tool descriptions rewritten to lead with returned scope (named fields/shapes), clarify workflow boundaries, and link sibling tools — total description payload shrinks ~14% while becoming more useful to LLM callers on every session start.
create_prompt,get_prompt, andupdate_promptretain a one-line hint pointing callers at the structuredmessagesalias while documenting the legacy JSON-encodedstringmulti-message format.create_api_key("the secret is only returned once"),delete_api_key("cannot be undone"), andinsert_log(failure mode for unmatchedrequest_provider) sharpened for safety-critical wording.- Voice/casing normalized across analytics tools (
Get Xrather than mixedReturn X/Returns X) and MCP tools (lowercaseidrather than mixedID/id).
- Three description-quality test blocks in
tests/unit.test.tsenforcing: workflow/scope/sibling guidance for weak tool families, A-rated/infra tool standards, and a high-risk sweep overdelete_*/create_api_key/create_virtual_key/run_prompt_completion/insert_logrequiring irreversibility, access, billable, or failure semantics in the description. Test count 101 → 102. - Shared
before()setup in the description-quality suite to register all tools once with adescriptionFor()helper, replacing per-testregisterAllToolsrebuilds.
@biomejs/biome2.4.10 → 2.4.12@types/node25.5.2 → 25.6.0dotenv17.4.1 → 17.4.2knip6.3.0 → 6.4.1lefthook2.1.5 → 2.1.6redis5.11.0 → 5.12.1- 0 vulnerabilities; full
npm run ci(lint + knip + typecheck + 102 unit tests + build + 16 e2e tests + readme tool verification) green.
0.3.0 - 2026-04-14
Tool surface refinement release. Cleans up a phantom endpoint, adds structured input aliases for LLM ergonomics, enables stdio/HTTP tool domain subsetting, and flags the 28 tools that are Enterprise-gated so clients know up front.
PORTKEY_TOOL_DOMAINSenvironment variable — stdio and HTTP clients can now expose only a focused subset of tools (e.g.prompts,analytics) instead of all 150. Validated againstTOOL_DOMAIN_NAMESon startup with a clear error listing valid domains. Complements the pre-existing HTTP-only?tools=query parameter.- Structured input aliases for prompt creation/update/migration —
create_prompt,update_prompt, andmigrate_promptnow accept a first-classmessagesarray (system/user/assistant with typed content blocks) alongside the legacy JSON-encodedstring. The server serializesmessagesinto the legacy format before calling Portkey, so both forms keep working. - Structured filter aliases on every analytics tool —
status_codes[],virtual_key_slugs[],config_slugs[],trace_ids[],span_ids[],provider_models[],metadata_filter{}, and array-awareapi_key_ids[]. LLM callers can now pass native arrays/objects; the server normalizes to Portkey's legacy comma-separated query params. - Enterprise-gated annotation on the 28 tools that require Portkey Enterprise plan scopes — 20 analytics tools,
list_audit_logs, 3 org-level integration reads, and 4 org-level user reads now carry anEnterprise-gated. Returns 403 on non-Enterprise Portkey plans.suffix in their descriptions. Verified against the Portkey dashboard — these scope groups are not offered to workspace plans. - Glama MCP server registry card badge in README and
glama.jsonownership manifest.
- BREAKING:
get_tracetool removed. Portkey's Admin API does not exposeGET /logs/{id}— the endpoint returns405 Method Not Allowedfor every valid-looking id and is absent from the official Portkey SDK. Single-trace retrieval is not a supported operation; usecreate_log_exportwith atrace_idfilter to export the data you need. This drops tool count from 151 → 150.
- All destructive-op descriptions (
delete_*,remove_*,reset_*) tightened for Glama TDQS scoring — each now documents cascade effects and a safety/audit step, matching the pattern of the already-strongdelete_virtual_key/delete_api_keydescriptions. Bumps min-TDQS on destructive tools and lifts the overall description quality score. - All 150 tool descriptions pass through a quality review for the Glama TDQS rubric — purpose clarity, usage guidelines, behavioral transparency, parameter semantics.
src/services/tracing.service.tsno longer exportsTrace,TraceSpan, orGetTraceResponsetypes (removed withget_trace).- README
API Key Scopessection rewritten to call out Enterprise gating explicitly, list every affected tool, and note that workspace service keys with Select All cover the non-Enterprise surface. - SECURITY.md advisory URL updated to the personal-repo location.
get_tracewas previously documented and registered but had never worked against the real Portkey API. Removing it eliminates a silent failure path for LLM clients that would otherwise hit a 405.
0.2.0 - 2026-04-08
Major hardening release. Fixes critical MCP spec compliance issues, adds tool annotations and structured responses, and significantly improves security defaults.
- MCP tool annotations on all 151 tools —
readOnlyHint,destructiveHint,idempotentHint,openWorldHintinferred from tool operation type outputSchemaon all tools viaregisterTool()— consistent{ok, data}/{ok, error}envelope for predictable LLM parsing- Server instructions — LLM guidance for tool selection ("Use list_* tools for discovery…")
MCP-Protocol-Versionheader validation — rejects post-init requests missing or mismatching the negotiated protocol version (spec 2025-06-18)- Per-request stateless MCP servers — each stateless request creates a fresh
McpServer+ transport, preventing cross-client data leaks (GHSA-345p-7cg4-v4c7) - Dynamic tool loading via
?tools=prompts,analyticsquery parameter — register only relevant tool domains per session to reduce token bloat - Session capacity management —
MCP_MAX_SESSIONSconfig (default 100) withtryReserve()/releaseReservation()to prevent overcommit during concurrent initializations MCP_PUBLIC_BASE_URL— explicit public URL for/auth/infoand status page, avoiding Host header trustMCP_ALLOW_UNAUTHENTICATED_HTTP— explicit opt-in for unauthenticated HTTP debugging (auth enforcement blocksMCP_AUTH_MODE=noneby default)RATE_LIMIT_MAX_BUCKETS— caps in-memory rate-limit buckets (default 10,000) with overflow sharing to bound memory- Helmet middleware for automatic HTTP security headers (CSP, HSTS, X-Content-Type-Options, etc.)
- Curated tool responses — list results include pagination metadata (
total,has_more,next_offset), analytics includepoint_count, prompt versions formatted compactly - Global tool error wrapper — unhandled exceptions in tool callbacks return
isError: trueinstead of crashing the MCP protocol - HTTP server integration tests — protocol version, session capacity, tool domain filtering, HSTS, auth rejection
- 108 tests total (93 unit + 15 E2E), up from ~40
z.union()inToolChoiceSchemasilently produced empty schema — replaced with flatz.object()+ discriminator field (SDK bug #1643)- Bearer token timing-safe comparison leaked token length — now compares fixed-length SHA-256 digests
- Rate limiter used raw
X-Forwarded-Forinstead ofreq.ip— trivially spoofable; now respects Expresstrust proxysetting ALLOWED_ORIGINSre-parsed on every request — now cached at module load- Default HTTP bind address was
0.0.0.0— changed to127.0.0.1to prevent accidental network exposure - Config JSON responses returned raw strings —
getConfig()andupdateConfig()now parseconfigfield into typed objects getPromptVersion()returnedRecord<string, unknown>— now typed asRawGetPromptResponse- CI badge pointed to wrong GitHub org (SYPartners → scttbnsn)
- Hardcoded
app/envenums in prompt tools — replaced withz.string()to allow arbitrary identifiers
- Default HTTP host:
0.0.0.0→127.0.0.1(setMCP_HOST=0.0.0.0explicitly for Docker/reverse proxy) - Service facade:
PortkeyServiceno longer delegates 400+ methods — domain services are now public readonly properties (service.users,service.analytics, etc.) BaseService: consolidated 4 HTTP methods into singleexecuteRequest()with shared logging/error handling- HTTP app architecture: extracted from
server.tsintolib/http-app.tsfor testability and reuse (Vercel, standalone, tests) InMemoryEventStore: throttled cleanup (every 30s instead of every write), per-event expiry checks, proper stream-index removalRedisEventStore: batched replay reads into single pipeline- Analytics tool responses: shared formatting helpers hoisted to module level, all responses include
point_count - All dependencies updated to latest (zod v4, express v5, MCP SDK v1.29+)
- Removed dependabot config (replaced with manual dep management)
- Added lefthook for pre-commit lint and pre-push checks
- Added knip for unused code detection
0.1.0 - 2026-03-28
First stable release. Graduates from beta with 151 tools covering ~98% of the Portkey Admin API surface.
- MCP Integrations (10 tools) — Full CRUD + metadata, capabilities, workspace access management for Portkey MCP integrations
- MCP Servers (10 tools) — Full CRUD + connectivity testing, capabilities, user access management for MCP servers
- Analytics: 8 new graph endpoints — error stacks, error status codes, user requests, rescued requests, feedback (4 variants)
- Analytics: 3 group endpoints — analytics grouped by user, model, or metadata key with pagination
- Prompt version management (2 tools) —
get_prompt_versionandupdate_prompt_versionfor individual version operations (e.g., assigning labels) - Usage limit entities (2 tools) —
list_usage_limit_entitiesandreset_usage_limit_entityfor entity-level usage tracking - API key
expires_atin update —update_api_keynow supports setting or clearing expiration dates .github/CODEOWNERSfor default code ownership.github/dependabot.ymlfor automated weekly dependency updates (npm + GitHub Actions)- Contract test for
GetPromptResponseSchemawith omittedversionsfield
- 7 CVEs patched — undici, hono, path-to-regexp, express-rate-limit, @hono/node-server, ajv, qs (5 high, 1 moderate, 1 low)
GetPromptResponseSchema.versionstoo strict — now optional with[]default, matching runtime API behaviorcreate_mcp_integrationsilent failure — now returnsisErrorwhenauth_type=headerswithoutcustom_headersupdate_prompt_versionallows no-op — now rejects calls with undefinedlabel_id(must pass explicit value ornull)- Prompt
update_promptreturns 400 whenstringfield included — Service now remapsstring→prompt_templatebefore sending to API - Partial
update_prompt_partialsilently dropsdescription— Service now remapsdescription→version_description list_prompt_partialscrashes with.map is not a function— API returns wrapped response, service now unwrapslist_partial_versions,list_prompt_versions— Same wrapped response fix- Guardrails
onFailtype mismatch — Aligned TypeScript interface with Zod schema (on_fail_action) - Sanitized real org/workspace/user UUIDs in test fixtures with synthetic values
- Deleted unused
virtual-keys-get.jsontest fixture
- Tool count: 116 → 151
- ENDPOINTS.md totals updated from 140+/107+ to 151/131
- Prompt tool descriptions clarified for multi-message JSON array format
0.1.0-beta.4 - 2026-03-28
- Pointed package URLs to personal repo for npm publishing
- README badge centering and footer improvements
0.1.0-beta.3 - 2026-03-02
- Initial public release with 116 tools
- Stdio and HTTP transports
- Clerk JWT and bearer token authentication
- Redis event store for stateless mode
- Vercel deployment support
- Contract tests, E2E tests, security tests