From 81da4fbce973024b2958e40edca79cee991a7d82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 01:14:51 +0000 Subject: [PATCH 1/2] chore(deps): bump zod from 3.25.76 to 4.4.2 Bumps [zod](https://github.com/colinhacks/zod) from 3.25.76 to 4.4.2. - [Release notes](https://github.com/colinhacks/zod/releases) - [Commits](https://github.com/colinhacks/zod/compare/v3.25.76...v4.4.2) --- updated-dependencies: - dependency-name: zod dependency-version: 4.4.2 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1cba085..52578e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "axios": "^1.7.0", "form-data": "^4.0.5", "md-to-adf": "^0.5.0", - "zod": "^3.22.4" + "zod": "^4.4.2" }, "bin": { "mcp-jira-stdio": "dist/index.js" @@ -5136,9 +5136,9 @@ } }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.2.tgz", + "integrity": "sha512-IynmDyxsEsb9RKzO3J9+4SxXnl2FTFSzNBaKKaMV6tsSk0rw9gYw9gs+JFCq/qk2LCZ78KDwyj+Z289TijSkUw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 2f08b18..a7164b0 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "axios": "^1.7.0", "form-data": "^4.0.5", "md-to-adf": "^0.5.0", - "zod": "^3.22.4" + "zod": "^4.4.2" }, "devDependencies": { "@types/node": "^25.3.3", From 5b44ac707af1ce27f8b937cde717b863dc06de8a Mon Sep 17 00:00:00 2001 From: Tomas Grasl Date: Tue, 16 Jun 2026 20:42:59 +0200 Subject: [PATCH 2/2] fix: migrate code and tests to zod v4 API zod v4 introduces breaking changes that broke typecheck and tests: - z.record() now requires an explicit key schema -> use z.record(z.string(), z.any()) - ZodError.errors was renamed to ZodError.issues - error messages changed ("Required" -> "Invalid input: expected ...") - the schema-internal _def.typeName ("ZodObject") was removed Tool tests no longer introspect zod internals; they assert validateInput was called with the actual exported schema, which is version-independent. validators test now matches zod v4 error message text. All 348 tests pass; typecheck and lint clean with zod 4.4.2. --- src/types/tools.ts | 2 +- src/utils/validators.ts | 2 +- tests/unit/tools/create-issue-link.test.ts | 10 ++-------- tests/unit/tools/create-issue.test.ts | 10 ++-------- tests/unit/tools/get-issue.test.ts | 10 ++-------- tests/unit/tools/search-issues.test.ts | 10 ++-------- tests/unit/utils/validators.test.ts | 4 ++-- 7 files changed, 12 insertions(+), 36 deletions(-) diff --git a/src/types/tools.ts b/src/types/tools.ts index 4d505b9..31d211e 100644 --- a/src/types/tools.ts +++ b/src/types/tools.ts @@ -61,7 +61,7 @@ export const CreateIssueInputSchema = z.object({ labels: z.array(z.string()).optional().describe('Issue labels'), components: z.array(z.string()).optional().describe('Component names'), customFields: z - .record(z.any()) + .record(z.string(), z.any()) .optional() .describe( 'Additional Jira field mappings, e.g. { "customfield_12345": value }. Use for required custom fields.' diff --git a/src/utils/validators.ts b/src/utils/validators.ts index 8b1ac90..7c22dc9 100644 --- a/src/utils/validators.ts +++ b/src/utils/validators.ts @@ -6,7 +6,7 @@ export function validateInput(schema: ZodSchema, input: unknown): T { return schema.parse(input); } catch (error) { if (error instanceof z.ZodError) { - const errorMessages = error.errors.map((err) => `${err.path.join('.')}: ${err.message}`); + const errorMessages = error.issues.map((err) => `${err.path.join('.')}: ${err.message}`); throw new Error(`${ERROR_MESSAGES.VALIDATION_ERROR}\n${errorMessages.join('\n')}`); } throw error; diff --git a/tests/unit/tools/create-issue-link.test.ts b/tests/unit/tools/create-issue-link.test.ts index 8de338c..1880d4f 100644 --- a/tests/unit/tools/create-issue-link.test.ts +++ b/tests/unit/tools/create-issue-link.test.ts @@ -4,6 +4,7 @@ import { createIssueLinkTool, } from '../../../src/tools/create-issue-link.js'; import { validateInput } from '../../../src/utils/validators.js'; +import { CreateIssueLinkInputSchema } from '../../../src/types/tools.js'; import { createIssueLink } from '../../../src/utils/api-helpers.js'; import { formatSuccessResponse } from '../../../src/utils/formatters.js'; import { handleError } from '../../../src/utils/error-handler.js'; @@ -194,14 +195,7 @@ describe('create-issue-link tool', () => { await handleCreateIssueLink(input); - expect(mockedValidateInput).toHaveBeenCalledWith( - expect.objectContaining({ - _def: expect.objectContaining({ - typeName: 'ZodObject', - }), - }), - input - ); + expect(mockedValidateInput).toHaveBeenCalledWith(CreateIssueLinkInputSchema, input); }); it('should handle validation errors for missing fromIssue', async () => { diff --git a/tests/unit/tools/create-issue.test.ts b/tests/unit/tools/create-issue.test.ts index cc5639d..504833a 100644 --- a/tests/unit/tools/create-issue.test.ts +++ b/tests/unit/tools/create-issue.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { handleCreateIssue, createIssueTool } from '../../../src/tools/create-issue.js'; import { validateInput } from '../../../src/utils/validators.js'; +import { CreateIssueInputSchema } from '../../../src/types/tools.js'; import { createIssue } from '../../../src/utils/api-helpers.js'; import { formatIssueResponse } from '../../../src/utils/formatters.js'; import { handleError } from '../../../src/utils/error-handler.js'; @@ -219,14 +220,7 @@ describe('create-issue tool', () => { await handleCreateIssue(input); - expect(mockedValidateInput).toHaveBeenCalledWith( - expect.objectContaining({ - _def: expect.objectContaining({ - typeName: 'ZodObject', - }), - }), - input - ); + expect(mockedValidateInput).toHaveBeenCalledWith(CreateIssueInputSchema, input); }); it('should handle validation errors for missing required fields', async () => { diff --git a/tests/unit/tools/get-issue.test.ts b/tests/unit/tools/get-issue.test.ts index 26f6fc9..e628196 100644 --- a/tests/unit/tools/get-issue.test.ts +++ b/tests/unit/tools/get-issue.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { handleGetIssue, getIssueTool } from '../../../src/tools/get-issue.js'; import { validateInput, extractIssueKey } from '../../../src/utils/validators.js'; +import { GetIssueInputSchema } from '../../../src/types/tools.js'; import { getIssue } from '../../../src/utils/api-helpers.js'; import { formatIssueResponse } from '../../../src/utils/formatters.js'; import { handleError } from '../../../src/utils/error-handler.js'; @@ -201,14 +202,7 @@ describe('get-issue tool', () => { await handleGetIssue(input); - expect(mockedValidateInput).toHaveBeenCalledWith( - expect.objectContaining({ - _def: expect.objectContaining({ - typeName: 'ZodObject', - }), - }), - input - ); + expect(mockedValidateInput).toHaveBeenCalledWith(GetIssueInputSchema, input); }); it('should handle validation errors', async () => { diff --git a/tests/unit/tools/search-issues.test.ts b/tests/unit/tools/search-issues.test.ts index 11c83ca..288e9de 100644 --- a/tests/unit/tools/search-issues.test.ts +++ b/tests/unit/tools/search-issues.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { handleSearchIssues, searchIssuesTool } from '../../../src/tools/search-issues.js'; import { validateInput } from '../../../src/utils/validators.js'; +import { SearchIssuesInputSchema } from '../../../src/types/tools.js'; import { searchIssues } from '../../../src/utils/api-helpers.js'; import { formatSearchResultsResponse } from '../../../src/utils/formatters.js'; import { handleError } from '../../../src/utils/error-handler.js'; @@ -207,14 +208,7 @@ describe('search-issues tool', () => { await handleSearchIssues(input); - expect(mockedValidateInput).toHaveBeenCalledWith( - expect.objectContaining({ - _def: expect.objectContaining({ - typeName: 'ZodObject', - }), - }), - input - ); + expect(mockedValidateInput).toHaveBeenCalledWith(SearchIssuesInputSchema, input); }); it('should handle validation errors for missing JQL', async () => { diff --git a/tests/unit/utils/validators.test.ts b/tests/unit/utils/validators.test.ts index b47db45..f4bb1c6 100644 --- a/tests/unit/utils/validators.test.ts +++ b/tests/unit/utils/validators.test.ts @@ -37,8 +37,8 @@ describe('validators', () => { it('should handle missing required fields', () => { const input = { age: 30 }; - expect(() => validateInput(testSchema, input)).toThrow('name: Required'); - expect(() => validateInput(testSchema, input)).toThrow('email: Required'); + expect(() => validateInput(testSchema, input)).toThrow('name: Invalid input'); + expect(() => validateInput(testSchema, input)).toThrow('email: Invalid input'); }); it('should rethrow non-zod errors', () => {