v3.1.0: remote MCP, tool improvements, response store, release pipeline#3
Merged
willwebster5 merged 4 commits intomasterfrom Apr 10, 2026
Merged
v3.1.0: remote MCP, tool improvements, response store, release pipeline#3willwebster5 merged 4 commits intomasterfrom
willwebster5 merged 4 commits intomasterfrom
Conversation
Push a v* tag to trigger lint/test/release pipeline. Validates SERVER_VERSION in client.py matches the tag, builds and pushes a Docker image to GHCR (versioned + latest), and creates a GitHub Release with auto-generated notes from commits since the last tag. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ackaging Add per-client authentication for HTTP transports so the MCP server can run remotely and credential-less. stdio mode is unchanged. Foundation: - FalconClient.deferred() — credential-less instance for HTTP mode - auth_object property guarded against deferred misuse - BaseModule._get_auth() / _service() — ContextVar-based per-request auth resolution with FalconPy services created on demand - _session_client ContextVar (canonical: modules/base.py) - SERVER_VERSION → 3.1.0 HTTP middleware stack (innermost → outermost): - session_auth_middleware: extracts X-Falcon-Client-* headers, authenticates via OAuth, caches sessions (25-min TTL, LRU max 100), sets ContextVar per request, returns 401 on missing/bad creds - auth_middleware: now also gates WebSocket scopes - with_health_check: outermost /health endpoint, no auth required Module refactor (8 of 10): hosts, response, spotlight, correlation, case_management, cloud_registration, cloud_security, cao_hunting now construct FalconPy services per-call via self._service(ServiceClass) instead of __init__. Supports the deferred FalconClient and per-request auth isolation. Existing test fixtures updated to mock _service. Server startup: - stdio: resolves credentials and authenticates eagerly (unchanged) - HTTP: deferred FalconClient, per-client auth via headers Container: - Dockerfile (python:3.12-slim, non-root mcp user, port 8000) - .dockerignore for clean build context Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… docs Reduce SOC agent friction observed during live triage by adding per-tool parameters that shrink response payloads server-side and enable bulk paging through large alert queues. get_alerts: - offset (int, default 0): native pagination via query_alerts_v2 - q (str): free-text search across all alert metadata, server-side - pattern_name: switched from client-side substring filter to server-side FQL wildcard (name:~*'*...*'). Composes with offset, removes the 4x over-fetch hack - max_results cap raised from 200 → 1000 - summary_mode (bool): compact key-fields rendering only - next_offset added to response for caller-side pagination alert_analysis: - summary_mode (bool): compact alert metadata + top 5 events with per-event-type field projection (NGSIEM/endpoint/cloud) ngsiem_query: - fields (str, comma-separated): server-side projection via appended `| select([...])`, skipped if query already has select() or table() - field_projection echoed in response FQL guides: - ALERT_FQL: full operator table (~, !~, *, ~*, ~*!), `now` timestamp keyword, name field correctly documented as filterable - HOST_FQL: wildcard operators section - Removes the now-incorrect "name is not a valid FQL field" note Module refactor: alerts.py and ngsiem.py both moved to the self._service() pattern as part of the v3.1.0 remote-MCP work shipped in the previous commit; bundled here because the file diffs interleave with the new feature parameters. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Keep the SOC triage agent inside the MCP tool loop when responses exceed the 20KB threshold. Structured tool output is now stored as Python dicts before text formatting, queryable via a new MCP tool instead of falling out to Bash/grep over a temp file. ResponseStore (root-level, peer to utils.py): - Singleton classmethod store with FIFO ring buffer (50 entries) - StoredResponse dataclass: ref_id, tool_name, timestamp, data, metadata, record_count - record_count derived generically from top-level list values - _reset() for test isolation modules/response_store.py — two new MCP tools: - get_stored_response: query by ref_id with record_index, record_key, fields (dot-path projection), search (case-insensitive), max_results - list_stored_responses: summary of all stored references - record_key lookup scans common ID fields (composite_id, @id, detection_id, user.name, ComputerName, source.ip, ...) utils.format_text_response now accepts optional structured_data and metadata kwargs: - When provided, the raw dict is stored and a ref_id is included in responses (footer for inline, full guidance for truncated) - Truncation notice surfaces a context line from metadata - Tools that don't pass structured_data keep the existing temp-file fallback unchanged Opt-in tools wired in the previous commit (alerts.alert_analysis, alerts.get_alerts, ngsiem.ngsiem_query) — they always store structured data so field-level extraction works on small responses too, not just on truncation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
willwebster5
added a commit
that referenced
this pull request
Apr 22, 2026
Read-only module mapping 1:1 to falconpy's ThreatGraph service collection (5 tools) plus one lazily-cached edge-types resource. Thin mapping preferred over composition; spec open question #1 (process-tree helper) deferred to v1.1 pending real agent traces. Spec open question #3 (edge-type drift) resolved via live cache. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
willwebster5
added a commit
that referenced
this pull request
Apr 22, 2026
Read-only module mapping 1:1 to falconpy's ThreatGraph service collection (5 tools) plus one lazily-cached edge-types resource. Thin mapping preferred over composition; spec open question #1 (process-tree helper) deferred to v1.1 pending real agent traces. Spec open question #3 (edge-type drift) resolved via live cache. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Four feature batches landing as v3.1.0. Implemented in dependency order: release pipeline → remote MCP foundation → tool improvements → response store. All 95 existing tests pass; lint and format clean.
1. Release Pipeline (
43abb46)Tag-driven
release.ymlworkflow. Push av*tag to lint, test, validate thatSERVER_VERSIONmatches the tag, build & push a Docker image to GHCR (versioned +latest), and publish a GitHub Release with auto-generated notes.2. Remote MCP Server (
8b5e24d) —SERVER_VERSION→ 3.1.0Per-client HTTP authentication so the server can run remotely and credential-less. stdio mode is unchanged.
FalconClient.deferred()for credential-less startup;auth_objectguarded against deferred misuseBaseModule._get_auth()/_service()resolve auth via a_session_clientContextVar (per-request isolation)common/session_auth.pymiddleware extractsX-Falcon-Client-Id/Secret/Base-Url, OAuths, caches sessions (25 min TTL, LRU max 100), sets the ContextVarcommon/health.pyASGI wrapper for/health(no auth)auth_middlewarenow also gates WebSocket scopes__init__service creation to per-callself._service(ServiceClass)Dockerfile(python:3.12-slim, non-root, port 8000) +.dockerignore3. MCP Tool Improvements (
7f0247f)Cuts SOC agent friction observed during live triage:
get_alerts:offset(native API pagination),q(server-side free-text search),pattern_namereimplemented as server-side FQL wildcard,max_resultscap raised to 1000,summary_modefor compact rendering,next_offsetin responsealert_analysis:summary_modewith per-event-type field projection (NGSIEM/endpoint/cloud)ngsiem_query:fieldsparameter for server-side| select([...])projection (skipped if query already hasselect()/table())~,!~,*,~*,~*!),nowtimestamp keyword, correctednamefield docs4. Response Store (
576f006)Keeps the SOC triage agent inside the MCP tool loop when responses exceed the 20KB threshold. Structured tool output is stored as Python dicts before text formatting and queried via a new MCP tool — no Bash/grep over temp files.
ResponseStoresingleton (FIFO ring buffer, 50 entries)get_stored_responsetool: query byref_idwithrecord_index,record_key(scans common ID fields),fields(dot-path projection),search,max_resultslist_stored_responsestool: summary of all stored referencesformat_text_response()opt-in via newstructured_dataandmetadatakwargs; tools that don't pass them keep the existing temp-file fallbackalert_analysis,get_alerts, andngsiem_queryalways store structured data (works on small responses too, not just truncation)Test plan
pytest tests/)ruff check .cleanruff format --check .cleanget_alerts/alert_analysis/ngsiem_querystreamable-http, hit/health, verify 401 withoutX-Falcon-Client-*headers, verify success with valid headersget_alerts(max_results=50, offset=0)thenoffset=50, verifynext_offsetandtotal_availableconsistencyalert_analysis, query the returnedref_idviaget_stored_responsev3.1.0-rc1tag in a fork to verify the release workflow end-to-end before cuttingv3.1.0Out of scope
ResponseStore🤖 Generated with Claude Code