Skip to content

fix(ghostwriter-readonly): require gql 4 and fastmcp 3.2 (ENG-8934) - #192

Merged
briangreunke merged 1 commit into
mainfrom
feat/eng-8934-ghostwriter-gql4
Oct 20, 2026
Merged

briangreunke merged 1 commit into
mainfrom
feat/eng-8934-ghostwriter-gql4

Conversation

@briangreunke

Copy link
Copy Markdown
Contributor

Problem

ghostwriter-readonly pinned gql[aiohttp,websockets]>=3.0,<4.0. gql 3 requires websockets<12, and fastmcp 3.2+ requires websockets>=15.0.1, so uv run resolved the MCP server to fastmcp 2.12.5 and mcp 1.16.0. Both versions have published security advisories. mcp 1.16.0 also fails at import on current pydantic:

ImportError: cannot import name 'eval_type_backport' from 'pydantic._internal._typing_extra'

This applies the same pin change as #175 (mythic-c2-readonly).

Changes

  • mcp/server.py, mcp/test_server.py: require fastmcp>=3.2.0 and gql[aiohttp,websockets]>=4.0.
  • skills/ghostwriter-readonly/scripts/ghostwriter_read.py: require gql[aiohttp,websockets]>=4.0.
  • _run_query (server) and run_query (skill script): set variable_values on the gql 4 request object instead of passing the deprecated variable_values= keyword to session.execute.
  • mcp/test_server.py: replace the removed FastMCP.get_tools() with list_tools(). Both tests still expect 22 tools.
  • mcp/test_server.py: add a test that runs _run_query against a local aiohttp stub. It checks that {"id": 7} reaches the request body as variables, that the stub's data is returned, and that no variable_values deprecation warning is raised.
  • capability.yaml: 1.0.0 → 1.0.1.

Evidence

Base 9814433e93cb4850b3b570077f3ca04b1fb8e258, head 7c26724a697aca4121ac35496d30548712d6060e. Python 3.13, linux x86_64.

  • uv tree --script on mcp/server.py and mcp/test_server.py: fastmcp v4.1.2, mcp v2.3.0, gql v4.4.0. On ghostwriter_read.py: gql v4.4.0.
  • uv run --python 3.13 --script capabilities/ghostwriter-readonly/mcp/test_server.py: 27 passed. The new stub test fails when _run_query is reverted to the variable_values= keyword.
  • uv run --python 3.13 --script .../scripts/ghostwriter_read.py --help: exit 0.
  • git grep -n 'variable_values=' -- <server.py> <ghostwriter_read.py>: no matches.
  • just validate strict=true: 26 validated, 0 failed (6 warnings for missing local binaries, unrelated).
  • pre-commit run --files <changed>: all hooks pass except ruff-format, which already fails on server.py and test_server.py at base. Reformatting would touch about 140 unrelated lines, so it is left out of this PR. CI does not run ruff-format.

Not tested against a live GhostWriter instance. ghostwriter_read.py has no automated test; it uses the same request pattern as the server.

🤖 Generated with Claude Code

The gql<4 cap forced dependency resolution to fastmcp 2.12.5 and mcp 1.16.0,
which carry known CVEs and fail at startup with
`ImportError: eval_type_backport`.

- Require gql>=4.0 and fastmcp>=3.2.0 in the server, test, and skill script
  PEP 723 headers.
- Send query variables on a gql 4 GraphQLRequest instead of the deprecated
  variable_values argument to session.execute.
- Replace the removed FastMCP.get_tools() with list_tools() in the tests.
- Add a test against a local HTTP stub that checks variables reach the wire
  and no deprecation warning is raised.
- Bump capability version to 1.0.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@briangreunke

Copy link
Copy Markdown
Contributor Author

Automated agent review (not a human approval)

Verdict: APPROVE, at head 7c26724a697aca4121ac35496d30548712d6060e against base 9814433e93cb4850b3b570077f3ca04b1fb8e258. No blocking findings.

Checked on Python 3.13, linux x86_64:

  • uv tree --script on mcp/server.py and mcp/test_server.py: fastmcp v4.1.2, mcp v2.3.0, gql v4.4.0. ghostwriter_read.py: gql v4.4.0.
  • mcp/test_server.py: 27 passed. Restoring the variable_values= keyword makes the new stub test fail.
  • Server started over stdio against a local GraphQL stub, listed 22 tools, and get_finding(id=7) sent "variables": {"id": 7}.
  • ghostwriter_read.py clients --limit 3 against a stub with PYTHONWARNINGS=always: exit 0, variables sent, no deprecation warning.
  • just validate strict=true: 0 failed.
  • CI: all checks pass.

Non-blocking: the stub test has two overlapping warning assertions.

@briangreunke
briangreunke merged commit 2d25a2f into main Oct 20, 2026
5 checks passed
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.

1 participant