Run gsage in your environment.
This page is the entry point into gsage's technical documentation. The authoritative source — including detailed developer docs, tool specs, and the full README — lives in the GitHub repositories below.
§Repositories
gsage is split across two source-available repositories on GitHub. Star them to follow releases.
The engine
Backend, web UI, MCP server, workers, scheduler and core agent orchestration. Start here to deploy gsage.
The tools
Community-contributed tools and integrations — connectors, enrichments, and adapters ready to plug into your deployment.
§Quick start
Install gsage with a single command:
$ curl -fsSL http://raw.githubusercontent.com/guardiankey/gsage-ai-soc/refs/heads/main/dist/get-gsage.sh | sudo bash
Installation details are available in the main repository: guardiankey/gsage-ai-soc.
§Tools & integrations
Tools are how gsage interacts with your environment. The platform is designed to make new integrations straightforward to add.
Tool model & execution
How tools are declared, registered, permissioned and executed through the MCP server.
docs/dev/TOOLS.md → CatalogueCommunity tools
Browse connectors and integrations contributed by the community. Drop-in tools for common SOC stacks.
gsage-ai-soc-tools → ContributePublish your tool
Recommended structure, metadata, tests, and the PR flow for publishing a tool others can reuse.
Contributing guide →The canonical guide for building tools lives in docs/dev/TOOLS.md. This page keeps only a short example aligned with the BaseTool API:
from __future__ import annotations from typing import ClassVar, Optional from src.mcp_server.tools.base import BaseTool, ToolResult from src.shared.security.context import AgentContext class MyTool(BaseTool): name: ClassVar[str] = "my_tool" version: ClassVar[str] = "1.0.0" summary: ClassVar[str] = "One-line summary used by search_tools" category: ClassVar[str] = "utility" permissions: ClassVar[list[str]] = ["utility:run"] params_schema: ClassVar[dict] = { "type": "object", "properties": {"value": {"type": "string"}}, "required": ["value"], } config_schema: ClassVar[Optional[dict]] = { "properties": {"prefix": {"type": "string"}}, } config_defaults: ClassVar[dict] = {"prefix": ""} async def execute( self, agent_context: AgentContext, params: dict, config: dict, state: dict, ) -> ToolResult: raw_value = params.get("value") if not isinstance(raw_value, str) or not raw_value.strip(): return self._failure("INVALID_INPUT", "'value' must be a non-empty string") return self._success({ "value": f"{config.get('prefix', '')}{raw_value.strip()}", "org_id": str(agent_context.org_id), })
§Contributing
Contributions are welcome, but they should be pragmatic and easy to review. Share tools and integrations others can use; avoid large refactors or architectural changes without prior discussion.
- open an issue first for significant changes;
- keep pull requests focused on one problem;
- include tests when behavior changes;
- update supporting docs when setup or usage changes;
- avoid mixing refactors with functional changes unless they are tightly coupled.
Before contributing, review docs/dev/. By submitting contributions, you agree to the terms described in LICENSE.
§Issues and support
If you find a bug, open an issue on GitHub. When reporting a problem, include:
- what you expected to happen;
- what actually happened;
- the service affected;
- relevant logs;
- reproduction steps;
- environment details (Docker version, OS, LLM provider).
If the issue involves secrets, credentials, or sensitive customer data, redact them before posting.