Skip to content

refactor(servers): replace wildcard imports with explicit exports and enforce tool import checks in CI - #328

Open
dandye wants to merge 6 commits into
mainfrom
fix__secops-splat-imports
Open

dandye wants to merge 6 commits into
mainfrom
fix__secops-splat-imports

Conversation

@dandye

@dandye dandye commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

1. Replace All Wildcard (from ... import *) Imports with Explicit Exports

Eliminates all 25 wildcard imports across all 391 tracked Python files in the repository:

  • server/secops/secops_mcp/tools/__init__.py: Replaces all 17 from .<module> import * lines with explicit imports of all 69 @server.tool() functions and an alphabetically sorted __all__ export list (preventing transitive symbol leakage such as logger, logging, datetime, and get_chronicle_client onto secops_mcp.tools).
  • server/gti/gti_mcp/tools/__init__.py: Replaces all 6 from .<module> import * lines with explicit imports of all 13 relationship constants, url_to_base64, and 36 @server.tool() functions, plus an alphabetically sorted __all__ export list.

2. Preserve Direct __main__ Script Execution (server.py)

  • server/secops/secops_mcp/server.py & server/gti/gti_mcp/server.py:
    • Previously, running server.py directly as a script (python server.py or uv run secops_mcp/server.py) loaded server.py as __main__, and importing tools loaded a second module copy (secops_mcp.server / gti_mcp.server) where @server.tool() decorators registered. Only the accidental leakage of server through from <pkg>.tools import * overwrote __main__.server with the populated second instance.
    • Replaces from <pkg>.tools import * with from <pkg> import tools # noqa: E402, F401 and aliases sys.modules.setdefault("<pkg>.server", sys.modules[__name__]) prior to importing tools so all @server.tool() decorators register on the single active FastMCP instance without double-loading server.py.

3. AST Tool Import/Export Audits & Negative Unit Tests

  • server/secops/tests/test_secops_tools_unit.py (_audit_secops_tools_exports) & server/gti/tests/test_tools.py (_audit_gti_tools_exports):
    • Parses every tools/*.py file on disk via ast.parse to enforce:
      1. Zero from ... import * wildcard imports in server.py, tools/__init__.py, or any tools/*.py submodule.
      2. Every public function or constant defined in tools/<submodule>.py is explicitly imported via from .<submodule> import ... in tools/__init__.py and listed in sorted tools.__all__, reporting file.py:lineno on any missing import or export.
      3. Every @server.tool() function discovered in tools/*.py is registered on server._tool_manager._tools both on standard module import (test_tools_init_explicit_exports_without_splat_imports, test_gti_tools_explicit_exports_without_splat_imports) and when running server.py as __main__ (test_server_main_script_execution_registers_all_tools, test_gti_server_main_script_execution_registers_all_tools).
      4. Every public function in server/secops/secops_mcp/tools/*.py carries @server.tool() (requiring internal helpers to be prefixed with _).
  • Negative unit tests (test_tools_init_flags_unimported_new_function, test_gti_tools_init_flags_unimported_new_function):
    • Copies tools/ to tmp_path, appends a new @server.tool() function to a submodule without updating tools/__init__.py, and verifies that the audit flags the exact file.py:lineno and symbol name for both the missing submodule import and missing __all__ entry.

4. GitHub Actions CI Workflow (.github/workflows/verify-tool-exports.yml)

  • Adds a pull request workflow running on ubuntu-latest (Python 3.11) with pinned test dependencies (pytest==9.1.1, pytest-asyncio==1.4.0, pytest-httpserver==1.2.0, pytest-mock==3.17.0) that executes:
    • pytest tests/*_unit.py -v in server/secops (41 passed)
    • pytest tests/ -v in server/gti (61 passed)

Verification

  • AST & Whitespace Checks: Verified 0 wildcard imports remain across all 391 tracked .py files and git diff --check reports zero whitespace errors.
  • Unit Test Suites (Local & GitHub Actions CI):
    • server/secops: 41 passed (tests/*_unit.py)
    • server/gti: 61 passed (tests/)
  • Live Argolis direnv MCP Verification (dandye-0324-chronicle):
    • Verified live stdio MCP tools/list (69 tools for secops_mcp, 36 tools for gti_mcp) and live Chronicle API tool execution (list_security_rules, search_security_events, get_security_alerts, get_ioc_matches, list_feeds, lookup_entity) in both -m <pkg>.server module mode and direct __main__ script mode.

@dandye dandye changed the title refactor(secops): replace wildcard imports in tools/__init__.py with explicit exports refactor(servers): replace all wildcard imports in secops and gti MCP servers with explicit exports Nov 1, 2026
@dandye
dandye marked this pull request as ready for review November 1, 2026 19:08
@dandye
dandye requested a review from a team November 1, 2026 19:08
@dandye dandye changed the title refactor(servers): replace all wildcard imports in secops and gti MCP servers with explicit exports refactor(servers): replace wildcard imports with explicit exports and enforce tool import checks in CI Nov 1, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant