Skip to content

[pull] main from czlonkowski:main - #66

Merged
pull[bot] merged 2 commits into
5474312:mainfrom
czlonkowski:main
May 14, 2026
Merged

[pull] main from czlonkowski:main#66
pull[bot] merged 2 commits into
5474312:mainfrom
czlonkowski:main

Conversation

@pull

@pull pull Bot commented May 14, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

czlonkowski and others added 2 commits May 14, 2026 11:52
…rkflow (#777) (#786)

* fix(workflow): strip duplicate activeVersion, add mode='active' (#777)

n8n's draft/publish model returns a nested activeVersion alongside the
draft on every workflow GET, duplicating the live graph's nodes and
connections. On active workflows this pushed responses past Claude
Code's default 25k-token MCP cap, so the host persisted results to a
temp file the model could not read.

handleGetWorkflow (mode 'full') and handleGetWorkflowDetails (mode
'details') now strip the heavy activeVersion payload while preserving
the activeVersionId pointer. A new mode 'active' exposes the published
graph as a single-shaped response (nodes/connections come from the live
version, with publishedAt and versionName at the top level), returning
NO_ACTIVE_VERSION for workflows that were never activated.

As defense in depth for genuinely huge workflows, the n8n_get_workflow
tool definition now declares _meta["anthropic/maxResultSizeChars"]:
500000 per the Claude Code MCP spec. UIAppRegistry.injectToolMeta now
spread-merges instead of clobbering so per-tool _meta keys survive UI
metadata injection.

Reported by @nepalez.

Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* review: simplify helper, prune type, rename publishedAt, tighten size cap

Apply code-simplifier, code-reviewer, and Copilot feedback on PR #786:

- stripActiveVersion: drop unnecessary generic and dead falsy guard.
  Plain (workflow: Workflow) => Workflow is fine — both call sites pass
  a full Workflow.
- ActiveWorkflowVersion: prune speculative fields (versionId, workflowId,
  authors, autosaved, description, updatedAt, workflowPublishHistory)
  that no consumer reads. Keep an open index signature so the additional
  keys on the wire don't cause type errors.
- handleGetWorkflowActive: rename publishedAt to versionCreatedAt — the
  value is activeVersion.createdAt, which is the version row's creation
  timestamp, not the publish-event time. n8n's workflowPublishHistory
  carries the actual activation event ~1s later. Don't claim equivalence.
  Also fall back to null when the source is missing.
- maxResultSizeChars: 500_000 → 450_000 to leave headroom for the
  MCP/JSON-RPC envelope wrapping our payload.
- Add regression tests: mode='full' must return the DRAFT nodes/connections
  (not the published ones) after the strip; pre-draft/publish n8n versions
  (no activeVersion key at all) must pass through unmangled.

No behavior change to the size-fix and mode='active' contracts.

Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: cover handleGetWorkflowActive error paths and mode dispatch

Codecov flagged 25 lines of patch coverage gap (70.93% → target). The
gap was concentrated in two places:

- handleGetWorkflowActive's catch ladder (Zod / N8nApiError / generic)
  — every other handler in this file has matching error tests but the
  new one didn't. Add four: invalid input, N8nApiError mapping, generic
  Error fall-through, and a defaults-to-null check on versionCreatedAt /
  versionName when the active version row carries no name or timestamp.

- src/mcp/server.ts's 'active' case in the n8n_get_workflow switch is
  trivial wiring but had no unit-level coverage. Add a focused dispatch
  test file that mocks handlers-n8n-manager via vi.hoisted and asserts
  mode='active' routes to handleGetWorkflowActive (and mode='details'
  and default route to their respective handlers as regression guards).

+7 tests, all green. No production code change.

Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: address Copilot follow-up review

- CHANGELOG: correct the documented size cap (450000, not 500000) so the
  release notes match the implementation after the earlier reviewer pass.
- handleGetWorkflowActive: fall back to workflow.nodes/connections when
  workflow.active is true but no activeVersionId/activeVersion is present.
  This makes mode='active' usable across n8n versions — pre-draft/publish
  n8n returns no activeVersion field at all, and on those instances the
  workflow body itself IS the running graph. The same branch covers the
  rare orphan case in newer n8n where activeVersionId got nulled but the
  workflow is still flagged active. NO_ACTIVE_VERSION now means "inactive
  and never published" specifically.
- Tests updated: the "active:true, no activeVersionId" path now asserts
  the fallback returns workflow.nodes; a separate "active:false, no
  activeVersionId" test pins the genuine never-activated case to
  NO_ACTIVE_VERSION. Added an orphaned-on-inactive test for completeness.
- Tool doc updated to describe the fallback and the narrower
  NO_ACTIVE_VERSION semantic.
- Force-track dist/mcp/ui/registry.* so Copilot stops flagging the gap —
  the file is regenerated by the release pipeline (npm run build:all
  before npm publish), but committing it removes the false-positive.

Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rebased #783 + #784) (#787)

* fix(http): preserve shared tenant sessions

(cherry picked from commit 7e9e274)

* fix(http): return 404 for stale sessions

(cherry picked from commit e855570)

* chore(dist): regenerate sourcemaps after cherry-picks

* test(http-session): tighten shared-mode assertion

The cherry-picked shared-mode regression test used
`not.toHaveBeenCalledWith(400)`, which would also pass on 500/etc. Mirror
the instance-mode test's tighter pattern: capture the existing transport
reference, then assert it remains the same object and its `close` mock
was never invoked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(changelog): document HTTP session fixes for 2.53.0

Add entries for #783 (preserve shared tenant sessions) and #784 (404 for
stale sessions) under the in-flight 2.53.0 section, both crediting
@LevSky22.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(changelog): drop dead 'malformed format' phrasing

isValidSessionId() accepts any non-empty string, so the "malformed
format" 400 branch is unreachable in practice. The changelog text now
mirrors the implemented behavior: 400 for missing session IDs on
non-initialize requests, 404 for unknown non-empty session IDs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: levsky22 <56281588+LevSky22@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pull pull Bot locked and limited conversation to collaborators May 14, 2026
@pull pull Bot added the ⤵️ pull label May 14, 2026
@pull
pull Bot merged commit de5241c into 5474312:main May 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant