Skip to content

Commit ec4aff2

Browse files
committed
docs: improve agents.md and add claude.md with reference to agents.md
1 parent b92ae9d commit ec4aff2

File tree

2 files changed

+230
-59
lines changed

2 files changed

+230
-59
lines changed

AGENTS.md

Lines changed: 229 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,142 @@
1-
# Sysdig MCP Server – Agent Handbook
1+
# Sysdig MCP Server – Agent Developer Handbook
22

3-
This document is optimized for MCP coding agents. It highlights what matters most when you need to explore the repository, extend a tool, or run validation quickly.
3+
This document is a comprehensive guide for an AI agent tasked with developing and maintaining the Sysdig MCP Server. It covers everything from project setup and architecture to daily workflows and troubleshooting.
44

5-
## Quick Facts
5+
## 1. Project Overview
6+
7+
**Sysdig MCP Server** is a Go-based Model Context Protocol (MCP) server that exposes Sysdig Secure platform capabilities to LLMs. It provides tools for querying runtime security events, Kubernetes metrics, and executing SysQL queries through multiple transport protocols (stdio, streamable-http, SSE).
8+
9+
### 1.1. Quick Facts
610

711
| Topic | Details |
812
| --- | --- |
9-
| Purpose | Expose vetted Sysdig Secure workflows to LLMs through MCP tools |
10-
| Entry point | `cmd/server/main.go` (Cobra CLI that wires config, Sysdig client, handler, transports) |
11-
| Runtime | Go 1.25+, uses `mcp-go`, `cobra`, `ginkgo/gomega`, `golangci-lint` |
12-
| Dev shell | `nix develop` (check `IN_NIX_SHELL=1` before hacking or running commands) |
13-
| Key commands | `just fmt`, `just lint`, `just test`, `just check`, `just test-coverage` |
13+
| **Purpose** | Expose vetted Sysdig Secure workflows to LLMs through MCP tools. |
14+
| **Tech Stack** | Go 1.25+, `mcp-go`, Cobra CLI, Ginkgo/Gomega, `golangci-lint`, Nix. |
15+
| **Entry Point** | `cmd/server/main.go` (Cobra CLI that wires config, Sysdig client, etc.). |
16+
| **Dev Shell** | `nix develop` provides a consistent development environment. |
17+
| **Key Commands** | `just fmt`, `just lint`, `just test`, `just check`, `just bump`. |
1418

15-
## Repository Layout
19+
## 2. Environment Setup
1620

17-
| Path | Ownership Notes |
18-
| --- | --- |
19-
| `cmd/server` | Cobra CLI + transport bootstrap; `setupHandler` registers every MCP tool. |
20-
| `internal/config` | Loads environment variables (`SYSDIG_MCP_*`) and enforces validation (stdio requires host/token). |
21-
| `internal/infra/mcp` | Generic MCP handler, HTTP/SSE middlewares, permission filtering logic. |
22-
| `internal/infra/mcp/tools` | One file per tool + `_test.go`. Helpers live in `utils.go`. |
23-
| `internal/infra/sysdig` | Typed Sysdig Secure client plus auth helpers (`WrapContextWithHost/Token`). |
24-
| `docs/` | Assets referenced from the README (diagrams, screenshots). |
25-
| `justfile` | Canonical dev tasks (format, lint, generate, test, dependency bump). |
26-
27-
## Day-to-Day Workflow
28-
29-
1. Assume you are in a Nix shell and you have all the available tools. Otherwise edit `flake.nix` to add any required tool you don't have in the PATH.
30-
2. Make focused changes (new MCP tool, bugfix, docs, etc.).
31-
3. Run the default quality gates:
32-
```bash
33-
just fmt # gofumpt -w .
34-
just lint # golangci-lint run
35-
just test # ginkgo -r -p (auto-runs `go generate ./...`)
36-
```
37-
4. Use `just check` to chain fmt+lint+test, and `just test-coverage` when you need coverage artifacts.
38-
5. Follow Conventional Commits when preparing PRs.
39-
6. In case you need to update or add more dependencies run `just bump`.
40-
41-
## MCP Tools & Permissions
42-
43-
The handler filters tools dynamically based on `GetMyPermissions` from Sysdig Secure. Each tool declares mandatory permissions via `WithRequiredPermissions`. Current tools (`internal/infra/mcp/tools`):
21+
### 2.1. Using Nix (Recommended)
22+
23+
The repository uses a Nix flake to ensure a consistent development environment with all required tools.
24+
25+
```bash
26+
# Enter the development shell with all tools available
27+
nix develop
28+
29+
# Or, if you use direnv, allow it to load the environment
30+
direnv allow
31+
```
32+
33+
### 2.2. Required Environment Variables
34+
35+
The server requires API credentials to connect to Sysdig Secure.
36+
37+
- `SYSDIG_MCP_API_HOST`: Sysdig Secure instance URL (e.g., `https://us2.app.sysdig.com`).
38+
- `SYSDIG_MCP_API_TOKEN`: Sysdig Secure API token.
39+
40+
For a full list of optional variables (e.g., for transport configuration), see the project's `README.md`.
41+
42+
## 3. Architecture
43+
44+
### 3.1. Repository Layout
45+
46+
```
47+
cmd/server/ - CLI entry point, tool registration
48+
internal/
49+
config/ - Environment variable loading and validation
50+
infra/
51+
clock/ - System clock abstraction (for testing)
52+
mcp/ - MCP server handler, transport setup, middleware
53+
tools/ - Individual MCP tool implementations
54+
sysdig/ - Sysdig API client (generated + extensions)
55+
docs/ - Documentation assets
56+
justfile - Canonical development tasks (format, lint, test, generate, bump)
57+
flake.nix - Defines the Nix development environment and its dependencies
58+
```
59+
60+
### 3.2. Key Components & Flow
61+
62+
1. **Entry Point (`cmd/server/main.go`):**
63+
- Cobra CLI that loads config, sets up Sysdig client, registers tools, and starts transport
64+
- `setupHandler()` registers all MCP tools (line 88-114)
65+
- `startServer()` handles stdio/streamable-http/sse transport switching (line 118-140)
66+
67+
2. **Configuration (`internal/config/config.go`):**
68+
- Loads environment variables with `SYSDIG_MCP_*` prefix
69+
- Validates required fields for stdio transport (API host and token mandatory)
70+
- Supports remote transports where auth can come via HTTP headers
71+
72+
3. **MCP Handler (`internal/infra/mcp/mcp_handler.go`):**
73+
- Wraps mcp-go server with permission filtering (`toolPermissionFiltering`, line 26-64)
74+
- Dynamically filters tools based on Sysdig API token permissions
75+
- HTTP middleware extracts `Authorization` and `X-Sysdig-Host` headers for remote transports (line 108-138)
76+
77+
4. **Sysdig Client (`internal/infra/sysdig/`):**
78+
- `client.gen.go`: Generated OpenAPI client (**DO NOT EDIT**, regenerated via oapi-codegen)
79+
- `client.go`: Authentication strategies with fallback support
80+
- Context-based auth: `WrapContextWithToken()` and `WrapContextWithHost()` for remote transports
81+
- Fixed auth: `WithFixedHostAndToken()` for stdio mode
82+
- Custom extensions in `client_extension.go` and `client_*.go` files
83+
84+
5. **Tools (`internal/infra/mcp/tools/`):**
85+
- Each tool has its own file: `tool_<name>.go` + `tool_<name>_test.go`
86+
- Tools implement `RegisterInServer(server *server.MCPServer)`
87+
- Use `WithRequiredPermissions()` from `utils.go` to declare Sysdig API permissions
88+
- Permission filtering happens automatically in handler
89+
90+
### 3.3. Authentication Flow
91+
92+
1. **stdio transport**: Fixed host/token from env vars (`SYSDIG_MCP_API_HOST`, `SYSDIG_MCP_API_TOKEN`)
93+
2. **Remote transports**: Extract from HTTP headers (`Authorization: Bearer <token>`, `X-Sysdig-Host`)
94+
3. Fallback chain: Try context auth first, then fall back to env var auth
95+
4. Each request includes Bearer token in Authorization header to Sysdig APIs
96+
97+
### 3.4. Tool Permission System
98+
99+
- Each tool declares its required Sysdig API permissions using `WithRequiredPermissions("permission1", "permission2")`.
100+
- Before exposing tools to the LLM, the handler calls the Sysdig `GetMyPermissions` API.
101+
- The agent will only see tools for which the provided API token has **all** required permissions.
102+
- Common permissions: `policy-events.read`, `sage.exec`, `risks.read`, `promql.exec`
103+
104+
## 4. Day-to-Day Workflow
105+
106+
1. **Enter the Dev Shell:** Always work inside the Nix shell (`nix develop` or `direnv allow`) to ensure all tools are available. You can assume the developer is already in a Nix shell.
107+
2. **Make Focused Changes:** Implement a new tool, fix a bug, or improve documentation.
108+
3. **Run Quality Gates:** Use `just` to run formatters, linters, and tests.
109+
4. **Commit:** Follow the Conventional Commits specification. Keep the commit messages short, just title, no description. Pre-commit hooks will run quality gates automatically.
110+
111+
### 4.1. Testing & Quality Gates
112+
113+
The project enforces quality through a series of checks.
114+
115+
```bash
116+
just fmt # Format Go code with gofumpt.
117+
just lint # Run the golangci-lint linter.
118+
just test # Run the unit test suite (auto-runs `go generate` first).
119+
just check # A convenient alias for fmt + lint + test.
120+
```
121+
122+
### 4.2. Pre-commit Hooks
123+
124+
This repository uses **pre-commit** to automate quality checks before each commit. The hooks are configured in `.pre-commit-config.yaml` to run `just fmt`, `just lint`, and `just test`.
125+
126+
This means that every time you run `git commit`, your changes are automatically formatted, linted, and tested. If any of these checks fail, the commit is aborted, allowing you to fix the issues.
127+
128+
If the hooks do not run automatically, you may need to install them first:
129+
```bash
130+
# Install the git hooks defined in the configuration
131+
pre-commit install
132+
133+
# After installation, you can run all checks on all files
134+
pre-commit run -a
135+
```
136+
137+
## 5. MCP Tools & Permissions
138+
139+
The handler filters tools dynamically based on the Sysdig user's permissions. Each tool declares mandatory permissions via `WithRequiredPermissions`.
44140

45141
| Tool | File | Capability | Required Permissions | Useful Prompts |
46142
| --- | --- | --- | --- | --- |
@@ -66,34 +162,108 @@ The handler filters tools dynamically based on `GetMyPermissions` from Sysdig Se
66162
| `troubleshoot_kubernetes_list_top_memory_consumed_by_workload` | `tool_troubleshoot_kubernetes_list_top_memory_consumed_by_workload.go` | Lists memory-intensive workloads (all containers). | `promql.exec` | "Show the top 10 workloads consuming the most memory in cluster 'production'" |
67163
| `troubleshoot_kubernetes_list_top_memory_consumed_by_container` | `tool_troubleshoot_kubernetes_list_top_memory_consumed_by_container.go` | Lists memory-intensive containers. | `promql.exec` | "Show the top 10 containers consuming the most memory in cluster 'production'" |
68164

69-
Every tool has a companion `_test.go` file that exercises request validation, permission metadata, and Sysdig client calls through mocks.
70-
Note that if you add more tools you need to also update this file to reflect that.
165+
## 6. Adding a New Tool
166+
167+
1. **Create Files:** Add `tool_<name>.go` and `tool_<name>_test.go` in `internal/infra/mcp/tools/`.
168+
169+
2. **Implement the Tool:**
170+
* Define a struct that holds the Sysdig client.
171+
* Implement the `handle` method, which contains the tool's core logic.
172+
* Implement the `RegisterInServer` method to define the tool's MCP schema, including its name, description, parameters, and required permissions. Use helpers from `utils.go`.
173+
174+
3. **Write Tests:** Use Ginkgo/Gomega to write BDD-style tests. Mock the Sysdig client to cover:
175+
- Parameter validation
176+
- Permission metadata
177+
- Sysdig API client interactions (mocked)
178+
- Error handling
179+
180+
4. **Register the Tool:** Add the new tool to `setupHandler()` in `cmd/server/main.go` (line 88-114).
181+
182+
5. **Document:** Add the new tool to the README.md and the table in section 5 (MCP Tools & Permissions).
183+
184+
### 6.1. Example Tool Structure
185+
186+
```go
187+
type ToolMyFeature struct {
188+
sysdigClient sysdig.ExtendedClientWithResponsesInterface
189+
}
190+
191+
func (h *ToolMyFeature) handle(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
192+
param := request.GetString("param_name", "")
193+
response, err := h.sysdigClient.SomeAPICall(ctx, param)
194+
// Handle response...
195+
return mcp.NewToolResultJSON(response.JSON200)
196+
}
197+
198+
func (h *ToolMyFeature) RegisterInServer(s *server.MCPServer) {
199+
tool := mcp.NewTool("my_feature",
200+
mcp.WithDescription("What this tool does"),
201+
mcp.WithString("param_name",
202+
mcp.Required(),
203+
mcp.Description("Parameter description"),
204+
),
205+
mcp.WithReadOnlyHintAnnotation(true),
206+
mcp.WithDestructiveHintAnnotation(false),
207+
WithRequiredPermissions("permission.name"),
208+
)
209+
s.AddTool(tool, h.handle)
210+
}
211+
```
212+
213+
### 6.2. Testing Philosophy
214+
215+
- Use BDD-style tests with Ginkgo/Gomega
216+
- Each tool requires comprehensive test coverage for:
217+
- Parameter validation
218+
- Permission metadata
219+
- Sysdig API client interactions (mocked using go-mock)
220+
- Error handling
221+
- Integration tests marked with `_integration_test.go` suffix
222+
- No focused specs (`FDescribe`, `FIt`) should be committed
223+
224+
## 7. Conventional Commits
225+
226+
All commit messages must follow the [Conventional Commits](https://www.conventionalcommits.org/) specification. This is essential for automated versioning and changelog generation.
227+
228+
- **Types**: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`, `build`, `ci`.
229+
- **Format**: `<type>(<optional scope>): <imperative description>`
230+
231+
## 8. Code Generation
232+
233+
- `internal/infra/sysdig/client.gen.go` is auto-generated from OpenAPI spec via oapi-codegen.
234+
- Run `go generate ./...` (or `just generate`) to regenerate after spec changes.
235+
- Generated code includes all Sysdig Secure API types and client methods.
236+
- **DO NOT** manually edit `client.gen.go`. Extend functionality in separate files (e.g., `client_extension.go`).
237+
238+
## 9. Important Constraints
239+
240+
1. **Generated Code**: Never manually edit `client.gen.go`. Extend functionality in separate files like `client_extension.go`.
241+
242+
2. **Service Account Limitation**: The `generate_sysql` tool does NOT work with Service Account tokens (returns 500). Use regular user API tokens for this tool.
243+
244+
3. **Permission Filtering**: Tools are hidden if the API token lacks required permissions. Check user's Sysdig role if a tool is unexpectedly missing.
245+
246+
4. **stdio Mode Requirements**: When using stdio transport, `SYSDIG_MCP_API_HOST` and `SYSDIG_MCP_API_TOKEN` MUST be set. Remote transports can receive these via HTTP headers instead.
71247

72-
## Adding or Updating Tools
248+
## 10. Troubleshooting
73249

74-
1. Create a new file in `internal/infra/mcp/tools/tool_<name>.go` plus `_test.go`.
75-
2. Implement a struct with a `handle` method and `RegisterInServer`; reuse helpers from `utils.go` (`Examples`, `WithRequiredPermissions`, `toPtr`, etc.).
76-
3. Cover all branches with Ginkgo/Gomega tests. Use the `tools_suite_test.go` suite for shared setup.
77-
4. Register the tool in `cmd/server/main.go` inside `setupHandler`.
78-
5. Document required permissions and sample prompts in both the README and MCP metadata.
250+
**Problem**: Tool not appearing in MCP client
251+
- **Solution**: Check API token permissions match tool's `WithRequiredPermissions()`. Use Sysdig UI: **Settings > Users & Teams > Roles**. The token must have **all** permissions listed.
79252

80-
## Testing & Quality Gates
253+
**Problem**: "unable to authenticate with any method"
254+
- **Solution**: For `stdio`, verify `SYSDIG_MCP_API_HOST` and `SYSDIG_MCP_API_TOKEN` env vars are set correctly. For remote transports, check `Authorization: Bearer <token>` header format.
81255

82-
- `just test` runs `go generate ./...` first, then executes the whole suite via Ginkgo (`-r -p` to parallelize). Avoid leaving focused specs (`FDescribe`, `FIt`) in committed code.
83-
- `just lint` runs `golangci-lint run` using the repo’s configuration (see `.golangci.yml` if adjustments are necessary).
84-
- `just test-coverage` emits `coverage.out`; open it with `go tool cover -func=coverage.out`.
85-
- For manual checks, `go test ./...` and `ginkgo ./path/to/package` work inside the Nix shell.
256+
**Problem**: Tests failing with "command not found"
257+
- **Solution**: Enter Nix shell with `nix develop` or `direnv allow`. All dev tools are provided by the flake.
86258

87-
## Troubleshooting & Tips
259+
**Problem**: `generate_sysql` returning 500 error
260+
- **Solution**: This tool requires a regular user API token, not a Service Account token. Switch to a user-based token.
88261

89-
- **Missing config:** `SYSDIG_MCP_API_HOST` and `SYSDIG_MCP_API_TOKEN` are mandatory in `stdio`. Validation fails early in `internal/config/config.go`.
90-
- **Token scope:** If a tool does not appear, verify the token’s permissions under **Settings > Users & Teams > Roles**. `generate_sysql` currently requires a regular user token, not a Service Account.
91-
- **Remote auth:** When using `streamable-http` or `sse`, pass `Authorization: Bearer <token>` and optionally `X-Sysdig-Host`. These values override env vars via the request context middleware.
92-
- **Environment drift:** Always run inside `nix develop`; lint/test expect binaries like `gofumpt`, `golangci-lint`, and `ginkgo` provided by the flake.
93-
- **Dependency refresh:** Use `just bump` (updates flake inputs, runs `go get -u`, `go mod tidy`, and rebuilds `package.nix`) when you truly need to refresh dependencies.
262+
**Problem**: Pre-commit hooks not running
263+
- **Solution**: Run `pre-commit install` to install git hooks, then `pre-commit run -a` to test all files.
94264

95-
## Reference Links
265+
## 11. Reference Links
96266

97-
- `README.md`comprehensive product docs, quickstart, and client configuration samples.
98-
- `pkg.go.dev/github.com/sysdiglabs/sysdig-mcp-server`use when checking published module versions.
99-
- [Model Context Protocol](https://modelcontextprotocol.io/)protocol reference for tool/transport behavior.
267+
- `README.md`Comprehensive product docs, quickstart, and client configuration samples.
268+
- `CLAUDE.md`Complementary guide with additional examples and command reference.
269+
- [Model Context Protocol](https://modelcontextprotocol.io/)Protocol reference for tool/transport behavior.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@AGENTS.md

0 commit comments

Comments
 (0)