Skip to content

fix: cover CPEX plugin regressions#4629

Merged
brian-hussey merged 6 commits into
mainfrom
fix/plugin-regression-tests
May 28, 2026
Merged

fix: cover CPEX plugin regressions#4629
brian-hussey merged 6 commits into
mainfrom
fix/plugin-regression-tests

Conversation

@lucarlig

@lucarlig lucarlig commented May 6, 2026

Copy link
Copy Markdown
Collaborator

🐛 Bug-fix PR

📌 Summary

Fixes CPEX migration regressions found after the internal plugin framework was replaced:

  • Runtime-facing external plugin launch/config paths needed to use cpex.framework.external.mcp.server.runtime instead of the deleted in-repo framework runtime.
  • prompt_post_fetch with CPEX hook policies could duplicate prompt messages when a post-hook modified nested prompt result content.
  • ResourceContent needed to serialize MCP resource MIME type as mimeType, not mime_type, on alias-aware dumps.
  • Server-scoped resources/read now has regression coverage for duplicate URI collisions, including time://formats style resources.

🔁 Reproduction Steps

  • Start an external plugin launcher or stdio config that imports the old deleted framework runtime path.
  • Run MCP prompts/get for mcp-plugin-parity-db-direct with PromptOutputSentinelPlugin enabled; before the fix it returned two identical messages after prompt_post_fetch.
  • Serialize ResourceContent(..., mime_type="text/plain") with model_dump(by_alias=True); the MCP response shape must use mimeType.
  • Read a server-scoped resource URI when another resource with the same URI exists outside that server; the server-scoped path must not fall back to an ambiguous global lookup.

🐞 Root Cause

  • The old in-repo framework package was removed, so runtime-facing imports must resolve through CPEX.
  • CPEX policy isolation wraps nested mutable fields. Passing a gateway PromptResult object directly into PromptPosthookPayload allowed the policy merge path to wrap and re-apply the nested messages list, producing duplicate messages.
  • ResourceContent did not inherit the alias-aware base model, so alias serialization did not consistently produce MCP camelCase.
  • Resource URI collisions across gateway/server associations require server filtering during lookup.

💡 Fix Description

  • Updated runtime-facing external plugin paths to use cpex.framework.external.mcp.server.runtime.
  • Added a direct import regression test proving the packaged CPEX external MCP runtime is importable.
  • Serialize prompt post-hook input to a plain payload before invoking CPEX and validate modified hook output back into the gateway PromptResult model.
  • Added a prompt post-hook regression test using the real CPEX plugin manager, real hook policy map, and the sentinel plugin.
  • Made ResourceContent use the alias-aware base model and added serialization coverage for mimeType.
  • Added resource service regressions for server-scoped URI lookup and generic ambiguous URI handling.

🧪 Verification

Check Command Status
Focused regression suite uv run pytest tests/unit/mcpgateway/plugins/test_cpex_migration_paths.py tests/unit/mcpgateway/test_schemas.py tests/unit/mcpgateway/services/test_prompt_service.py tests/unit/mcpgateway/plugins/plugins/test_prompt_output_sentinel.py -q --tb=short Passed
Targeted resource lookup regressions uv run pytest tests/unit/mcpgateway/services/test_resource_service.py::TestReadResourceCoverageEdges::test_read_resource_server_scoped_uri_lookup_avoids_duplicate_uri_collisions tests/unit/mcpgateway/services/test_resource_service.py::TestReadResourceCoverageEdges::test_read_resource_generic_uri_lookup_reports_ambiguity -q --tb=short Passed
Lint uv run ruff check tests/unit/mcpgateway/plugins/test_cpex_migration_paths.py mcpgateway/services/prompt_service.py tests/unit/mcpgateway/services/test_prompt_service.py mcpgateway/common/models.py tests/unit/mcpgateway/test_schemas.py Passed
Whitespace git diff --check Passed
Linked CPEX source compatibility PYTHONPATH=/tmp/contextforge-plugins-framework uv run pytest tests/unit/mcpgateway/plugins/test_cpex_migration_paths.py tests/unit/mcpgateway/services/test_prompt_service.py::TestPromptService::test_get_prompt_post_hook_policy_does_not_duplicate_prompt_messages tests/unit/mcpgateway/plugins/plugins/test_prompt_output_sentinel.py tests/unit/mcpgateway/test_schemas.py::TestMCPTypes::test_resource_content_serializes_mcp_mime_type_alias -q --tb=short Passed
Manual regression no longer fails Raw local MCP prompts/get request against a fresh plugin-enabled server returned one sentinel-appended message Passed

📐 MCP Compliance (if relevant)

  • Matches current MCP spec
  • No breaking change to MCP clients

✅ Checklist

  • Code formatted (make black isort pre-commit)
  • No secrets/credentials committed

@lucarlig lucarlig marked this pull request as ready for review May 6, 2026 14:34
@lucarlig lucarlig requested a review from cafalchio May 6, 2026 14:35
cafalchio
cafalchio previously approved these changes May 6, 2026

@cafalchio cafalchio left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

lucarlig added 5 commits May 28, 2026 14:12
Signed-off-by: lucarlig <luca.carlig@ibm.com>
Signed-off-by: lucarlig <luca.carlig@ibm.com>
Signed-off-by: lucarlig <luca.carlig@ibm.com>
Signed-off-by: lucarlig <luca.carlig@ibm.com>
Signed-off-by: lucarlig <luca.carlig@ibm.com>
@lucarlig lucarlig force-pushed the fix/plugin-regression-tests branch from 8ea8c75 to abe3f31 Compare May 28, 2026 13:22
@brian-hussey brian-hussey self-assigned this May 28, 2026
Signed-off-by: Brian Hussey <brian.hussey@ie.ibm.com>

@brian-hussey brian-hussey left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved based on previous approval.

@brian-hussey brian-hussey merged commit 079cbe2 into main May 28, 2026
46 checks passed
@brian-hussey brian-hussey deleted the fix/plugin-regression-tests branch May 28, 2026 13:41
@brian-hussey

Copy link
Copy Markdown
Member

Tests previously passed, only outstanding issue was .secrets.baseline update, merged once that passed.

@cafalchio cafalchio mentioned this pull request Jun 10, 2026
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants