feat(toolboxes): use codeql_ql_mcp toolbox for consistent multi-language CodeQL MCP integration#224
Conversation
Make `codeql-development-mcp-server` (ql-mcp) the standard
CodeQL MCP backend for seclab agents, replacing the
per-language toolboxes under `mcp_servers/codeql/`.
ql-mcp:
- is deeply integrated with taskflow-agent concepts and features;
- covers all 10 CodeQL-supported languages in one server;
- ships bundled tools queries (PrintAST, PrintCFG, CallGraph*);
- provides MCP tools for, amonth other things, direct (LSP)
integration with the CodeQL Langauge Server;
- exposes a SARIF analysis pipeline and an annotation/audit store;
- is maintained alongside the CodeQL CLI.
The new `codeql_ql_mcp` toolbox is the agent-facing surface for that
backend; the Docker image and devcontainer are updated to install
ql-mcp and its tool query packs so the toolbox works out of the box.
Also fixes an `mcp_utils` bug uncovered by this work: an
empty `args: []` in a toolbox YAML was being coerced to
`None`, which `StdioServerParameters` rejects for `stdio` based
integrations like the `ql-mcp` server.
Verified: 167/167 pytest tests pass.
There was a problem hiding this comment.
Pull request overview
This PR standardizes CodeQL MCP integration around the multi-language codeql-development-mcp-server (“ql-mcp”) by introducing a new codeql_ql_mcp toolbox, updating container/devcontainer setup to install its runtime dependencies, and fixing a stdio parameter-resolution bug in mcp_utils.
Changes:
- Add
codeql_ql_mcptoolbox YAML and tests validating parsing/configuration expectations. - Fix
mcp_utils.mcp_client_paramsto preserve emptyargs: [](instead of coercing toNone) for stdio/streamable toolboxes. - Update Docker image and devcontainer to install Node.js and
codeql-development-mcp-server+ its CodeQL packs.
Show a summary per file
| File | Description |
|---|---|
src/seclab_taskflow_agent/mcp_utils.py |
Preserve empty stdio args lists during toolbox param resolution. |
src/seclab_taskflow_agent/toolboxes/codeql_ql_mcp.yaml |
New unified ql-mcp toolbox config + extensive server prompt. |
tests/test_mcp_utils.py |
Regression tests for empty args handling in stdio toolboxes. |
tests/test_codeql_ql_mcp.py |
Validates the new toolbox YAML loads and contains expected fields/docs. |
docker/Dockerfile |
Installs Node.js + pins ql-mcp install and sets default env/volumes for toolbox. |
.devcontainer/devcontainer.json |
Adds Node feature (v24) needed for ql-mcp. |
.devcontainer/post-create.sh |
Installs ql-mcp and its packs in the devcontainer after creation. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 7/7 changed files
- Comments generated: 3
| RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \ | ||
| && apt-get install -y nodejs \ |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR standardizes CodeQL MCP integration around the multi-language codeql-development-mcp-server (“ql-mcp”) by introducing a new codeql_ql_mcp toolbox, updating container/devcontainer setup to install the ql-mcp backend, and fixing stdio args: [] handling in mcp_utils.
Changes:
- Add
codeql_ql_mcptoolbox YAML and tests validating its configuration. - Fix
mcp_client_paramsto preserve an empty stdioargs: [](instead of coercing it toNone). - Update Dockerfile and devcontainer provisioning to install Node +
codeql-development-mcp-serverand its query packs.
Show a summary per file
| File | Description |
|---|---|
tests/test_mcp_utils.py |
Adds regression tests for stdio args handling (empty list vs None). |
tests/test_codeql_ql_mcp.py |
Validates the new toolbox YAML parses and contains expected env mappings and prompt content. |
src/seclab_taskflow_agent/toolboxes/codeql_ql_mcp.yaml |
New toolbox config targeting the codeql-development-mcp-server stdio backend. |
src/seclab_taskflow_agent/mcp_utils.py |
Adjusts stdio/streamable arg coercion to preserve empty lists. |
docker/Dockerfile |
Installs Node and the ql-mcp npm package + packs; sets env defaults for the new toolbox. |
.devcontainer/post-create.sh |
Installs ql-mcp and packs in the devcontainer after creating the Python env. |
.devcontainer/devcontainer.json |
Adds Node feature to devcontainer configuration. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
src/seclab_taskflow_agent/mcp_utils.py:188
- In the stdio branch,
server_params["args"]is always set (including whenargs is None). IfStdioServerParametersrejectsNone(as noted in the comment), this will still fail whenever a toolbox omitsargs:or sets it to null. Consider omitting theargskey entirely whensp.args is None, or normalizingNoneto[]for stdio params to avoid validation errors.
env = dict(sp.env) if sp.env else None
# Note: must distinguish None from empty list. An empty list is
# a valid value (e.g. a binary that takes no args) and must be
# passed through to StdioServerParameters as `[]`, not `None`.
args = list(sp.args) if sp.args is not None else None
logging.debug(f"Initializing toolbox: {tb}\nargs:\n{args}\nenv:\n{env}\n")
if env:
for k, v in list(env.items()):
try:
env[k] = swap_env(v)
except LookupError as e:
logging.critical(e)
logging.info("Assuming toolbox has default configuration available")
del env[k]
logging.debug(f"Tool call environment: {env}")
if args:
for i, v in enumerate(args):
args[i] = swap_env(v)
logging.debug(f"Tool call args: {args}")
server_params["command"] = sp.command
server_params["args"] = args
server_params["env"] = env
- Files reviewed: 7/7 changed files
- Comments generated: 2
| def test_none_args_stays_none(self) -> None: | ||
| tb_name = "stub.none_args" | ||
| toolbox = _make_toolbox( | ||
| ServerParams(kind="stdio", command="some-binary", args=None, env=None) | ||
| ) | ||
| params = mcp_client_params(_StubAvailableTools({tb_name: toolbox}), [tb_name]) | ||
|
|
||
| assert params[tb_name][0]["args"] is None |
| # Install seclab-taskflow-agent from PyPI | ||
| # For local testing with unpublished changes, replace with: | ||
| # COPY . /app/seclab-taskflow-agent-src | ||
| # RUN pip install /app/seclab-taskflow-agent-src | ||
| RUN pip install seclab-taskflow-agent |
Summary
This PR is a proposal to make
codeql-development-mcp-server(aka "ql-mcp" server) the standard CodeQL MCP backend forseclab-taskflow-agent, including deprecation of the per-language toolboxes undermcp_servers/codeql/**in favor of a unifiedcodeql_ql_mcptoolbox for multi-language support.Repo -> advanced-security/codeql-development-mcp-server
Purpose
This integration is intended to reduce the maintenance burden related to CodeQL MCP for this repo, where the
ql-mcpserver:PrintAST,PrintCFG, andCallGraph*queries as part of reachability analysis;seclab-taskflow-agentrepo);ql-mcpreleases closes followcodeqlCLI releases;actionsc / cppcsharpgojava## and Kotlinjavascript## and TypeScript, HTML, XML, JSON, etc.pythonrubyrustswiftThe new
codeql_ql_mcptoolbox is the agent-facing surface for that backend; the Docker image and devcontainer are updated to install ql-mcp and its tool query packs so that thecodeql_ql_mcptoolbox works when run as a local Docker container.Related Changes
Also fixes an
mcp_utilsbug uncovered by this work: an emptyargs: []in a toolbox YAML was being coerced toNone, whichStdioServerParametersrejects forstdiobased integrations like theql-mcpserver.