Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ These terms describe **how tools and their related properties are represented**
- **`Tool Factory`**: A function wrapper `(options) => Tool` (internal).
- **`Tool Module`**: The programmatic result of `createMcpTool`, representing a collection of tools.
- **`JSON Schema` (`plain object`)**: A plain object intended as JSON Schema (for example `type`, `properties`, `required`). Converted toward Zod where possible via `jsonSchemaToZod` / `fromJSONSchema`.
- **`Zod schema`**: A Zod schema instance. Loosely detected with `isZodSchema`.
- **`Zod schema`**: A Zod schema instance. Loosely detected with `isZodSchema` (Zod 4 `_zod` / public `.def`, Zod 3 `_def`).
- **`Raw Zod shape` (`ZodRawShapeCompat`)**: A **non-empty** plain object whose **values** are Zod schemas; keys are field names. An empty `{}` is **not** a raw Zod shape. Detected with `isZodRawShape`.

## Initial troubleshooting
Expand Down
1 change: 1 addition & 0 deletions guidelines/skills/review-zod-integration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ description: Reviews Zod dependency upgrades for PatternFly MCP—maps release n
4. **Impact matrix**
- For **every** release-note bullet (breaking, fixes, performance, locales), add one row to the report tables. Columns: **Release note**, **Used in PF MCP?** (Yes / No / Indirect — cite file or grep), **Impact** (None / Low / Medium / High), **Priority**, **Recommended fix** (or `None`). Priority rules: [reference.md — Priority rules](reference.md#priority-rules-pf-mcp).
- Always include [reference.md — Updated P2 recommendations (Recurring)](reference.md#updated-p2-recommendations-recurring) in the report **Recommended fixes** section, even when tests pass.
- In **Documentation and agent guidance**, compare `guidelines/agent_coding.md` Zod detection text to `isZodSchema` in `src/server.schema.ts`; note match or drift on the `guidelines/agent_coding.md` row (see [reference.md — Report template](reference.md#report-template)).
- Row patterns: [reference.md — Example impact rows](reference.md#example-impact-rows-pf-mcp).

5. **Tests**
Expand Down
17 changes: 10 additions & 7 deletions guidelines/skills/review-zod-integration/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@

| File | Zod role |
|---------------------------------------|-------------------------------------------------------------------------------------------------------------------------------|
| `src/server.schema.ts` | `isZodSchema`, `isZodRawShape`, `jsonSchemaToZod`, `normalizeInputSchema`, `zodToJsonSchema`; v3 `_def` / v4 `_zod` detection |
| `src/server.schema.ts` | `isZodSchema`, `isZodRawShape`, `jsonSchemaToZod`, `normalizeInputSchema`, `zodToJsonSchema`; v3 `_def`, v4 `_zod`, public `.def` detection |
| `src/server.tools.ts` | `z.looseObject({})` Tools Host fallback |
| `src/server.toolsHost.ts` | Normalize plugin schemas; manifest JSON Schema via `zodToJsonSchema` |
| `src/server.toolsUser.ts` | `normalizeInputSchema` for inline/static tools |
| `src/options.assertions.ts` | `z.array(z.string().url().refine(...))` |
| `src/tool.patternFlyDocs.ts` | Raw Zod shape (`z.array`, `z.string`, `z.enum`, `.optional()`) |
| `src/options.assertions.ts` | `z.array(z.url().refine(...))` |
| `src/tool.patternFlyDocs.ts` | Raw Zod shape (`z.url()`, `z.array`, `z.string`, `z.enum`, `.optional()`) |
| `src/tool.searchPatternFlyDocs.ts` | Same |
| `src/tool.searchPatternFly.ts` | Same (experimental context-management search tool) |
| `src/__tests__/server.schema.test.ts` | Conversion tests + `toJSONSchema` snapshots |
Expand Down Expand Up @@ -61,7 +61,8 @@ If release notes only mention these, impact is usually **None**:
| `toJSONSchema` | `zodToJsonSchema`, default `draft-2020-12` |
| `z.object` / raw shapes | Built-in tools, `normalizeInputSchema` |
| `z.looseObject` | `server.schema.ts`, `server.tools.ts`; Standard for "open" tool inputs in Zod 4.4+ |
| `z.string().url()` + `.refine` | `options.assertions.ts` |
| `z.url()` + `.refine` | `options.assertions.ts` |
| `z.url()` | `tool.patternFlyDocs.ts` (`urlList`) |
| `z.enum`, `.optional()`, `.max()`, `.min()` | Tool input schemas |

## Dependencies
Expand Down Expand Up @@ -164,11 +165,13 @@ Save as: **`reports/YYYYMMDD-HHMMSS-zod-{semver}-update-report.md`** (`YYYYMMDD-

## Documentation and agent guidance

Compare `guidelines/agent_coding.md` (Zod detection) to `isZodSchema` in `src/server.schema.ts`; record match or drift on the `guidelines/agent_coding.md` row.

| Asset | Status |
|-------|--------|
| `docs/development.md` | |
| `docs/examples/*` | |
| `guidelines/agent_coding.md` | |
| `guidelines/agent_coding.md` | Match or drift vs `isZodSchema` |
| `tests/e2e/` | |

---
Expand Down Expand Up @@ -221,7 +224,7 @@ Use these as patterns when mapping **your** target release notes. Re-grep the co
| Required keys with `z.undefined()` | No — tools use `.optional()` on keys | None | None | None |
| `.merge()` throws when receiver has refinements | No — no `.merge()` | None | None | None |
| `toJSONSchema()` strips redundant `id` in `$defs` | Yes — `zodToJsonSchema`, Tools Host manifest | Low — no code reads `$defs.id` | None | None; re-run `server.schema` snapshots if manifest output changed |
| `z.httpUrl()` stricter URL validation | No — uses `z.string().url()` + `refine` in `options.assertions.ts` | None | None | None |
| `z.httpUrl()` stricter URL validation | No — uses `z.url()` + `refine` in `options.assertions.ts` | None | None | None |
| Floating-point accuracy (`multipleOf`) | No — `multipleOf` not used in schemas | None | None | None |

### Other fixes — sample rows
Expand Down Expand Up @@ -289,6 +292,6 @@ These items MUST be included in the "Recommended Fixes (P2)" section of the repo

- **DO**: Add detection for the public `.def` property (Zod 4.4+).
- **DO**: Update `docs/development.md` to recommend JSON Schema or Zod 4 for *new* plugins.
- **DO**: Migrate `z.string().url()` to `z.url()` where applicable (Zod 4.4+).
- **DO**: Prefer `z.url()` over `z.string().url()` in new code (Zod 4.4+); grep `src/` for stragglers during reviews.
- **DO NOT**: Remove the v3 `_def` branch in `isZodSchema`.
- **DO NOT**: Remove the `passthrough()` fallback in `jsonSchemaToZod` while plugin/tool authors may supply Zod v3 schemas (even when the server pins Zod 4). Revisit only if PF MCP explicitly drops v3 plugin compatibility.
2 changes: 1 addition & 1 deletion src/options.assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const assertProtocol = (
{ codeOrError }: { codeOrError?: AssertCodeOrError } = {}
) => {
const validate = z.array(
z.string().url().refine(
z.url().refine(
url => {
try {
const urlScheme = new URL(url).protocol;
Expand Down
9 changes: 9 additions & 0 deletions src/server.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ const isZodSchema = (value: unknown): boolean => {
}
}

// Zod v4 public `.def` (when `_zod` is absent); keep additive alongside v3 `_def` below
if (has('def') && obj.def && typeof obj.def === 'object') {
const def = obj.def as Record<string, unknown>;

if (typeof def.type === 'string' && isFunc(obj.parse) && isFunc(obj.safeParse)) {
return true;
}
}

// Zod v3 detection: `_def` object with both parse and safeParse functions
if (has('_def') && obj._def && typeof obj._def === 'object') {
if (isFunc(obj.parse) && isFunc(obj.safeParse)) {
Expand Down
Loading