fix(mcp): enforce env regex on every create_* tool (BUG-MCP-003/010)#32
Merged
Merged
Conversation
…(BUG-MCP-003/010)
The api enforces `env` against the regex `^[a-z0-9-]{1,32}$` (see
api/internal/handlers/env.go + the `invalid_env` 400 branch).
Pre-fix the MCP schema declared `env` as a bare `z.string()` so:
- `env: "HACKERLAND"` (uppercase) reached the api, got 400 → confusing
extra round-trip
- `env: <33-chars>` reached the api → same
- the JSON-Schema served by `tools/list` had no `pattern` field, so
host agents (Claude / Cursor / Windsurf) with strict JSON-Schema
enforcement also couldn't pre-flight the value
Fix: extract the api regex into a single `ENV_REGEX` constant, build an
`envSchema` ZodOptional wrapping the regex + `.optional()`, and reuse
it from `envArg` (the shared spread used by create_postgres,
create_vector, create_cache, create_nosql, create_queue, create_webhook,
create_storage). create_deploy and create_stack get an inline copy of
the same regex so their input contracts stay grep-visible in one block
each. Single source of truth = ENV_REGEX, drift risk = nil.
Coverage block (per CLAUDE.md rule 17):
Symptom: env=HACKERLAND accepted client-side, only api 400's it
Enumeration: rg -n 'env: z' src/index.ts (3 hits — envArg + create_deploy + create_stack)
Sites found: 3 (all 9 envelope tools route through one of these 3)
Sites touched: 3
Coverage test: env-regex-unit.test.ts iterates the registered tool list
from `server._registeredTools` so adding a future
create_* tool that forgets to apply the regex fails the
test by construction (registry-iterating, not hand-typed).
Live verify: call create_postgres({name:"x", env:"HACKERLAND"}) →
immediate zod error "env must match ^[a-z0-9-]{1,32}$"
Test results: 36 new test cases (4 per env-bearing tool × 9 tools),
total mcp suite = 323 tests, 0 failures.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes BUG-MCP-003 and BUG-MCP-010 from the 2026-05-29 QA wave.
What broke
The api enforces
envagainst^[a-z0-9-]{1,32}$(invalid_env400).The MCP schema declared
envas a barez.string(). Effect:env=HACKERLAND(uppercase) orenv=<33 chars>and the validation failure only surfaced from the api as a confusing 400 round trip.tools/listJSON Schema had nopatternfield to render to the user, so they couldn't pre-flight the value either.What the fix does
ENV_REGEX = /^[a-z0-9-]{1,32}$/.envSchemaZodOptional and reuse fromenvArg— used by the 7 shared-shape tools.Test coverage
New
test/env-regex-unit.test.tsis registry-iterating (per rule 18): it walksserver._registeredTools, finds every tool that exposesenv, and asserts:env.safeParse("HACKERLAND")fails (BUG-MCP-010 — uppercase rejected)env.safeParse("a".repeat(33))fails (BUG-MCP-003 — over-32 rejected)env.safeParse("staging")succeeds (positive)env.safeParse(undefined)succeeds (optional)A future create_* tool that forgets to apply the regex fails this test by construction.
Total mcp suite: 323 tests, 0 failures.
Rule 22 surface checklist
mcp/src/index.ts— env regex applied toenvArg,create_deploy.env,create_stack.envmcp/package.json— env-regex-unit added to test scriptsmcp/test/env-regex-unit.test.ts— registry-iterating regression testAPI behaviour is unchanged — this PR brings the MCP client into line with the api's existing regex. CLAUDE.md / OpenAPI docs already reflect the api's regex; no doc edits required.
Drift discipline
npm run test:nocov(323 tests) still passes.🤖 Generated with Claude Code