Setup
Add the nano-investigator MCP server to your agent with npx, configure it against your nano deployment, and verify the connection
Setup
nano-investigator runs as a local MCP server that your agent launches over stdio. It's published to npm as @nano-rs/investigator-mcp-server, so there's nothing to clone or build — npx fetches and runs it. Setup is a single MCP config block pointing at your nano deployment with an API key.
Requirements
- Node.js >= 20.0.0 (provides
npx) - A running nano instance reachable from where the server runs
Install
Add the MCP server to your agent
Add an entry to your MCP config (~/.claude/settings.json, or a project-level .mcp.json). npx resolves the published package on first launch, so the only values you supply are the environment variables:
{
"mcpServers": {
"nano-investigator": {
"command": "npx",
"args": ["-y", "@nano-rs/investigator-mcp-server"],
"env": {
"NANOSIEM_API_URL": "https://nanosiem.example.com:3000",
"NANOSIEM_API_KEY": "your-api-key",
"NANOSIEM_SEARCH_URL": "https://nanosiem.example.com:3002"
}
}
}
}The hosts and key above are placeholders. Replace them with your deployment's values. On a unified (install.sh) deployment, set NANOSIEM_API_URL to your base URL and omit NANOSIEM_SEARCH_URL — nginx routes /api/search* for you.
Pin a version for reproducibility — "args": ["-y", "@nano-rs/investigator-mcp-server@0.1.0"] — or install it globally (npm i -g @nano-rs/investigator-mcp-server) and set "command": "nano-investigator" to skip the per-launch npx resolution.
Restart your agent
Restart the agent so it picks up the new MCP server. In Claude Code, run /mcp to confirm nano-investigator shows as connected.
Environment variables
The server reads exactly three environment variables. No others are consulted.
| Var | Required | Default | Notes |
|---|---|---|---|
NANOSIEM_API_URL | Yes | none (throws if missing) | Main API, port 3000. A trailing slash is stripped. |
NANOSIEM_API_KEY | Yes | none (throws if missing) | Sent as the X-API-Key header on every request. |
NANOSIEM_SEARCH_URL | No | falls back to NANOSIEM_API_URL | Search service, port 3002. Used for /api/search* calls. |
.env loading
The server also loads .env and .env.local, walking up to three parent directories from where it starts. It never overrides a variable that is already set in the environment, so an explicit value in your MCP config or shell always wins.
Request timeout
Every API request uses a fixed 60000 ms timeout. This is not configurable through an environment variable.
API key permissions
The server authenticates with a single API key in the X-API-Key header. A nano key carries an explicit permission list set when you create it — it does not inherit a role — and the backend checks every request against that list. Scope the key to exactly the capabilities you'll use; a leaked least-privilege key can't do more than the agent could.
If the backend runs with AUTH_ENABLED=false (a development-only mode), permission checks are skipped entirely and any key works. Never rely on that in production.
Permissions by capability
get_schema and health_check need no permission — their endpoints are unauthenticated.
| Capability | Permissions | Access |
|---|---|---|
Search & query (search_sql, search, explain_query, get_field_values) | search:execute, search:sql ¹ | read |
| Saved / shared searches | search:view, search:save, search:share | read / write |
Source types (get_source_types) | search:view | read |
| Alerts | alerts:view | read |
| Cases — read | cases:view | read |
| Cases — write | cases:edit, cases:assign ², cases:comment ³ | write |
| Notebooks — read | notebooks:view | read |
| Notebooks — write | notebooks:create, notebooks:edit, notebooks:share | write |
| Detections (read) | detections:view | read |
| MITRE | mitre:view | read |
| Entities & risk | risk:view | read |
Enrichment (lookup_ip) | enrichments:view ⁴ | read |
| Prevalence | prevalence:view | read |
Org context (get_org_context) | settings:ai | read |
Audit trail (get_audit_trail) | audit:view | read |
| Parsers — read | log_sources:view, source_configs:view, parser_repositories:view | read |
| Parsers — author & deploy | log_sources:create, log_sources:edit, log_sources:deploy, source_configs:edit, parser_repositories:sync, parser_repositories:import | write |
¹ search:sql is only needed for the raw-SQL search_sql tool. ² assign_case needs cases:assign. ³ add_case_wall_entry needs cases:comment. ⁴ lookup_ip (GeoIP) needs enrichments:view. There's no IOC-lookup tool — IOC matching is applied at ingest into the ioc_matched / ioc_threat_type / ioc_confidence columns, so hunt it with search / search_sql (no extra permission).
Minimal vs full key
Read-only investigation — hunt, triage, and review with no mutation:
[
"search:view", "search:execute", "search:sql",
"alerts:view",
"cases:view",
"notebooks:view",
"detections:view",
"mitre:view",
"risk:view",
"enrichments:view",
"prevalence:view"
]Drop search:sql if you don't use search_sql. Add log_sources:view, source_configs:view, and parser_repositories:view to browse parsers read-only.
Full — adds case/notebook writes and parser authoring + deploy:
[
"search:view", "search:execute", "search:sql", "search:save", "search:share",
"alerts:view",
"cases:view", "cases:edit", "cases:assign", "cases:comment",
"notebooks:view", "notebooks:create", "notebooks:edit", "notebooks:share",
"detections:view", "mitre:view", "risk:view", "enrichments:view", "prevalence:view",
"audit:view", "settings:ai",
"log_sources:view", "log_sources:create", "log_sources:edit", "log_sources:deploy",
"source_configs:view", "source_configs:edit",
"parser_repositories:view", "parser_repositories:sync", "parser_repositories:import"
]Create a scoped key
In the nano UI go to Settings → API Keys and create a key with just the permissions above — you can only grant permissions your own account holds. Or call the API directly (the caller needs apikeys:create):
curl -X POST https://your-nano.example.com:3000/api/api-keys \
-H "Content-Type: application/json" \
-d '{"name":"mcp-investigator","permissions":["search:view","search:execute","..."],"expires_at":"2026-12-31T00:00:00Z"}'Pass the returned key as NANOSIEM_API_KEY.
Scope to least privilege. The investigator never needs detections:edit (that's nanodac's job), users:*, roles:*, apikeys:*, or settings:* beyond settings:ai. Leave out the parser write permissions (log_sources:*, source_configs:edit, parser_repositories:sync/import) unless the agent will author and deploy parsers.
Verify it works
Once the server shows as connected, ask the agent to run health_check. The tool checks ClickHouse and PostgreSQL connectivity through the API and returns the status of both. A healthy response confirms that the API URL, the key, and the backend are all reachable.
If the agent reports a connection error, re-check NANOSIEM_API_URL and NANOSIEM_API_KEY in the MCP config, and confirm the deployment is reachable from where the server runs.
What's next
- Triage: work the alert queue and open cases
- Investigate: run an alert investigation end to end
- Hunt: hunt entities and campaigns
- Tool Reference: every tool, prompt, and resource