Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Agentic Misp

FreeNot checked

Gives AI agents analyst-oriented workflows for MISP threat intelligence, including IOC search, pivot, event summarization, report generation, and controlled wri

GitHubEmbed

About

Gives AI agents analyst-oriented workflows for MISP threat intelligence, including IOC search, pivot, event summarization, report generation, and controlled write proposals with safety and audit logging.

README

MISP workflows for agents — investigate, pivot, report, and propose controlled writes without turning your MCP server into a raw API proxy.

agentic-misp-mcp is an MCP (Model Context Protocol) server that lets AI agents work with MISP threat intelligence safely. Instead of exposing the whole MISP API, it exposes 25 bounded, analyst-oriented workflows: search an IOC, investigate its context, pivot through related indicators, summarize events, check warninglists, observe feed health, generate reports, and prepare tightly controlled write proposals.

The safety model is simple and enforced in code:

  • Read-first. Every investigation tool is read-only; writes are disabled by default.
  • Approval-gated writes. The four write tools require write mode, a permitted role, and an explicit approval step — in production mode, a one-time operator-approved request ID.
  • Audit logging. Every tool call (allowed, blocked, failed, or errored) is written to a JSONL audit log with sanitized arguments.
  • Redaction. API keys, approval tokens, and feed secrets never appear in responses or logs.
  • Role policy. read_only / analyst_write / curator / admin roles bound what any agent session can even attempt.

Compatibility baseline: live-validated against MISP 2.5.42 (most recently the v0.3.0 release, 14/14 live checks — see docs/live-validation-report-v0.3.0.md). Other MISP versions are untested; see docs/misp-compatibility.md.

Who is this for?

  • SOC analysts — ask an agent to investigate an IOC and get verdict, confidence, freshness, related events, and next steps instead of raw JSON dumps.
  • Threat intelligence analysts — pivot, correlate, and produce Markdown/JSON reports from live MISP data.
  • Detection engineers — extract actionable (to_ids) indicators and event context with bounded, predictable output.
  • Security automation teams — wire MISP into agent workflows without handing the agent an unrestricted API key surface.
  • Regulated / banking environments — every call is audited, writes need out-of-band operator approval, and the write surface is small and explicit.

What can it do?

Workflow Tools involved
IOC investigation search_ioc, investigate_ioc, check_warninglists, pivot_ioc, find_related_iocs
Event search and context search_events, summarize_event, explain_event_context, extract_event_iocs, find_events_by_tag
Sightings get_ioc_sightings (read), add_sighting_with_approval (gated write)
Warninglist checks check_warninglists, plus automatic checks inside investigate_ioc
Feed observability (read-only) list_feeds, get_feed_status, summarize_feed_health
Markdown / JSON reporting generate_ioc_report, generate_event_report, generate_markdown_ioc_report, generate_markdown_event_report
Approval-gated writes submit_ioc_with_approval, add_sighting_with_approval, tag_event_with_approval, publish_event_with_approval
Age-aware scoring / stale-intel labeling investigate_ioc, generate_ioc_report, pivot_ioc — see Scoring behavior

The 25 tools

Access levels: read-only (never writes to MISP), dry-run (builds a reviewable payload, never calls a MISP write endpoint), approval-gated write (blocked unless write mode, role, and approval all allow it).

Investigation and read tools

Tool Access What it does
search_ioc(value, limit) read-only Find normalized MISP attribute matches for an indicator.
investigate_ioc(value, limit) read-only Verdict, confidence, freshness, warninglists, related events, next steps.
pivot_ioc(value, limit) read-only Pivot from one IOC into related context.
find_related_iocs(value, limit) read-only Rank related indicators worth hunting.
summarize_event(event_id) read-only Bounded event summary (never full raw event JSON).
explain_event_context(event_id) read-only What an event appears to represent.
extract_event_iocs(event_id, limit) read-only Extract supported IOC types from an event.
find_events_by_tag(tag, limit) read-only Events associated with a tag.
search_events(date_from, date_to, published, org, limit) read-only Discover events by bounded date/publication/org filters.
get_ioc_sightings(value, limit) read-only Bounded sighting summaries for an IOC.
check_warninglists(value) read-only Check an IOC against MISP warninglists.
get_misp_status() read-only MISP version and warninglist capability status.

Feed observability

Tool Access What it does
list_feeds(limit, enabled) read-only List configured feeds with bounded, redacted metadata.
get_feed_status(feed_id) read-only One feed's redacted status and fetch/cache age.
summarize_feed_health(limit) read-only Group feeds by health label (fresh/stale/never-fetched/disabled).

Feed enable/disable/fetch/cache/edit/delete remain operator-only MISP admin actions and are not exposed as MCP tools. See docs/feed-observability.md.

Reporting

Tool Access What it does
generate_ioc_report(value) read-only Deterministic structured (JSON) IOC report.
generate_event_report(event_id) read-only Deterministic structured (JSON) event report.
generate_markdown_ioc_report(value) read-only Markdown IOC report for notes/escalation.
generate_markdown_event_report(event_id) read-only Markdown event report.

Proposal (dry-run) tools

Tool Access What it does
propose_event(...) dry-run Build and validate an event-creation proposal. Never writes to MISP.
propose_attribute(...) dry-run Build and validate an attribute-creation proposal. Never writes to MISP.

Approval-gated write tools

Tool Access What it does
submit_ioc_with_approval(...) approval-gated write Add an attribute to an event.
add_sighting_with_approval(...) approval-gated write Record a sighting.
tag_event_with_approval(...) approval-gated write Tag an event.
publish_event_with_approval(...) approval-gated write Publish an event (curator/admin roles only).

Write-tool results are explicit: blocked, invalid, pending_approval, executed, or failed (MISP itself rejected the write). There are no silent writes. See docs/approval-flow.md.

Quick start

Prerequisites: Python 3.11+ and uv (or Docker — see Docker), a reachable MISP instance, and a MISP API key.

# 1. Clone and install
git clone https://github.com/hdyrawan/agentic-misp-mcp.git
cd agentic-misp-mcp
uv sync --extra dev

# 2. Configure (at minimum MISP_URL and MISP_API_KEY)
cp .env.example .env
# edit .env

# 3. Validate configuration (no MISP connection is made; the API key is redacted)
uv run agentic-misp-mcp config-check

# 4. Run the test suite
uv run --extra dev pytest -q

# 5. Start the MCP server over stdio (the primary supported transport)
uv run agentic-misp-mcp --transport stdio

Then:

  1. Connect an MCP client — see MCP client examples below.

  2. Run a first read-only toolget_misp_status is a good zero-risk smoke test; it confirms connectivity and reports the MISP version.

  3. Review the audit output:

    tail -n 20 logs/audit.jsonl | jq .
    

A good first-five sequence for a new operator, all read-only: get_misp_statuscheck_warninglistsinvestigate_iocsearch_eventssummarize_feed_health.

Docker

docker build -t agentic-misp-mcp:local .

# keep the env file outside the repository; never commit real credentials
mkdir -p /path/to/runtime/logs
cp .env.example /path/to/runtime/.env   # edit it

docker run --rm --env-file /path/to/runtime/.env \
  -v /path/to/runtime/logs:/app/logs \
  agentic-misp-mcp:local config-check

docker run --rm -i --env-file /path/to/runtime/.env \
  -v /path/to/runtime/logs:/app/logs \
  agentic-misp-mcp:local --transport stdio

Prefer Compose? See docker-compose.example.yml and docs/configuration.md.

Production note: the Dockerfile declares /app/logs and /app/approvals as VOLUMEs. If you run the image with docker run --rm and omit the -v bind mounts shown above, Docker silently creates anonymous volumes for both paths instead — audit logs and the approval database then disappear when the container is removed. Always bind-mount both paths explicitly in any production-write deployment.

Configuration

All configuration is via environment variables (or an .env file). Placeholders below are fake — never commit real credentials.

Required

Variable Example Notes
MISP_URL https://misp.example.local Base URL of your MISP instance.
MISP_API_KEY your_misp_api_key_here Runtime-only automation key. Loaded from the environment only; never passed as a tool argument.

Connection and output bounds (optional)

Variable Default Notes
MISP_VERIFY_TLS true Keep true in production. false is for isolated labs with self-signed certificates only — prefer adding your internal CA to the trust store instead.
MISP_TIMEOUT_SECONDS 30 HTTP timeout, > 0 and <= 300.
MISP_DEFAULT_LIMIT 20 Default result limit.
MISP_MAX_LIMIT 100 Maximum accepted result limit.
MISP_EVENT_ATTRIBUTE_LIMIT 50 Attribute cap for event summaries/investigations.
MISP_RELATED_EVENT_LIMIT 5 Related-event expansion cap.
AGENTIC_MISP_MCP_MAX_RESPONSE_BYTES 5242880 Max MISP HTTP response body size, enforced (fail-closed) before JSON parsing.

Safety and policy (optional)

Variable Default Notes
AGENTIC_MISP_MCP_ROLE read_only read_only, analyst_write, curator, or admin — see docs/roles.md.
AGENTIC_MISP_MCP_ENABLE_WRITE false Global write-mode gate. Leave false unless you need writes.
AGENTIC_MISP_MCP_REQUIRE_APPROVAL true Lab-mode gate requiring explicit approved=true; production mode requires an approval_request_id regardless.
AGENTIC_MISP_MCP_APPROVAL_MODE lab lab = programmatic approved=true flow; production = persisted, operator-approved, one-time-use request IDs.
AGENTIC_MISP_MCP_APPROVAL_TOKEN unset Optional lab shared-secret hardening; redacted in audit logs. Not the production approval mechanism.
AGENTIC_MISP_MCP_APPROVAL_STORE_PATH ./approvals.sqlite3 SQLite store for production approvals. The agent must not have write access to it. Persist it.
AGENTIC_MISP_MCP_APPROVAL_TTL_SECONDS 900 Production approval lifetime.
AGENTIC_MISP_MCP_ALLOWED_ATTRIBUTE_TYPES unset Production guardrail: allowlist of submittable attribute types.
AGENTIC_MISP_MCP_ALLOWED_ATTRIBUTE_CATEGORIES unset Production guardrail: allowlist of attribute categories.
AGENTIC_MISP_MCP_ALLOWED_TAGS unset Production guardrail: allowlist of event tags (* suffix = prefix match).
AGENTIC_MISP_MCP_ENABLE_PUBLISH false Dedicated publish kill switch; publish also requires curator/admin role and approval.
AGENTIC_MISP_MCP_AUDIT_LOG_PATH ./logs/audit.jsonl JSONL audit log path. Persist it (mount a volume under Docker).
AGENTIC_MISP_MCP_LOG_LEVEL INFO Application log level.
AGENTIC_MISP_MCP_ALLOW_INSECURE_HTTP_BIND false Experimental HTTP transport refuses non-loopback binds unless this is set. Keep false.

Age-aware scoring and feed freshness (optional, v0.3.0+)

Variable Default Notes
AGENTIC_MISP_MCP_AGE_WEIGHTING true Age-aware IOC scoring. false reproduces v0.2.x scoring exactly (the freshness block is emitted either way).
AGENTIC_MISP_MCP_FRESHNESS_FRESH_DAYS 30 Newest signal at or below this age is fresh.
AGENTIC_MISP_MCP_FRESHNESS_AGING_DAYS 90 Upper bound for aging.
AGENTIC_MISP_MCP_FRESHNESS_STALE_DAYS 365 Upper bound for stale; older is expired.
AGENTIC_MISP_MCP_AGE_WEIGHTS 1.0,0.75,0.4,0.15 Score multipliers for fresh/aging/stale/expired, each 0–1.
AGENTIC_MISP_MCP_FEED_FRESH_DAYS 7 Feed fetch/cache age at or below this is fresh.
AGENTIC_MISP_MCP_FEED_STALE_DAYS 30 Feed fetch/cache age above this is stale.

Full reference and examples: docs/configuration.md. Before any production run, also use the deeper check:

uv run agentic-misp-mcp config doctor

It validates write/approval-mode pairing, approval-store and audit-log permission safety, allowlist coverage, and more — without connecting to MISP or printing secrets.

MCP client examples

All examples use the stdio transport (the primary supported transport) and generic paths — replace /path/to/agentic-misp-mcp with your checkout (e.g. /home/user/agentic-misp-mcp or /opt/agentic-misp-mcp).

Stdio launcher scripts (recommended)

stdio MCP clients (Hermes, Claude Desktop, Claude Code, etc.) start this server as a subprocess and do not source your shell's rc files or the repo .env. Pointing a client straight at uv run agentic-misp-mcp --transport stdio can therefore fail (e.g. Hermes reporting "Connection closed") because MISP_URL/MISP_API_KEY are never visible to the subprocess.

The repo ships two wrapper scripts that load an env file and then exec the real command:

  • scripts/agentic-misp-mcp-stdio — starts the MCP server over stdio.
  • scripts/agentic-misp-mcp-config-check — runs config-check with the same env loading, so you can confirm MISP_URL/MISP_API_KEY resolve correctly before wiring up a client.

Both scripts resolve the repo root from their own file location (not your current working directory), then load ${AGENTIC_MISP_ENV_FILE} if that variable is set, otherwise <repo-root>/.env if it exists. Neither script echoes env values or secrets.

# Validate configuration before connecting a client
scripts/agentic-misp-mcp-config-check

# Point a stdio MCP client at the launcher, e.g. Hermes:
hermes mcp add agentic-misp-mcp --command "/path/to/agentic-misp-mcp/scripts/agentic-misp-mcp-stdio"

# Use an env file stored outside the repo instead of <repo-root>/.env
AGENTIC_MISP_ENV_FILE=/path/to/secure/agentic-misp.env scripts/agentic-misp-mcp-config-check

Never commit .env (or any file referenced via AGENTIC_MISP_ENV_FILE) — it holds MISP_API_KEY and other secrets. .gitignore already excludes .env by default.

MCP Inspector (smoke testing)

npx @modelcontextprotocol/inspector \
  uv --directory /path/to/agentic-misp-mcp run agentic-misp-mcp --transport stdio

Headless/CI mode (no browser):

npx -y @modelcontextprotocol/inspector --cli \
  uv --directory /path/to/agentic-misp-mcp run agentic-misp-mcp \
  --method tools/list

On a headless host, either use --cli mode or forward the Inspector UI ports over SSH: ssh -L 6274:localhost:6274 -L 6277:localhost:6277 [email protected].

Claude Code

claude mcp add agentic-misp-mcp -s local -- \
  uv --directory /path/to/agentic-misp-mcp run agentic-misp-mcp --transport stdio

Verify with claude mcp list (should show ✔ Connected), then start a new Claude Code session — tools appear in sessions started after the add. Remove with claude mcp remove agentic-misp-mcp -s local. Avoid -s project unless every teammate has the same paths, since it writes a shared .mcp.json verbatim.

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "agentic-misp-mcp": {
      "command": "uv",
      "args": [
        "--directory", "/path/to/agentic-misp-mcp",
        "run", "agentic-misp-mcp", "--transport", "stdio"
      ],
      "env": {
        "MISP_URL": "https://misp.example.local",
        "MISP_API_KEY": "your_misp_api_key_here"
      }
    }
  }
}

Prefer --env-file/OS-level secrets over inlining the key when your client supports it, and never commit a client config containing a real key.

Docker (any MCP client)

If the client spawns a subprocess (as Claude Desktop, OpenCode, and Hermes do above), point it at docker run instead of uv. Bind-mount /app/logs and /app/approvals explicitly — see the production note in Docker — and never bake MISP_URL/MISP_API_KEY into the image:

{
  "mcpServers": {
    "agentic-misp-mcp": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "--env-file", "/path/to/runtime/.env",
        "-v", "/path/to/runtime/logs:/app/logs",
        "-v", "/path/to/runtime/approvals:/app/approvals",
        "agentic-misp-mcp:local",
        "--transport", "stdio"
      ]
    }
  }
}

Hermes Agent

Hermes spawns the server as a subprocess and does not load the repo .env, so use the stdio launcher script rather than invoking uv directly:

hermes mcp add agentic-misp-mcp --command "/path/to/agentic-misp-mcp/scripts/agentic-misp-mcp-stdio"

Hermes performs a live discovery handshake and prompts to enable tools — answer y for all 25, or use select to enable a read-only subset (everything except the four _with_approval and two propose_* tools). Verify with hermes mcp list / hermes mcp test agentic-misp-mcp, then start a new Hermes session.

OpenCode (or similar local agent CLIs)

{
  "mcp": {
    "agentic-misp-mcp": {
      "type": "local",
      "command": [
        "uv", "--directory", "/path/to/agentic-misp-mcp",
        "run", "agentic-misp-mcp", "--transport", "stdio"
      ],
      "environment": {
        "MISP_URL": "https://misp.example.local",
        "MISP_API_KEY": "your_misp_api_key_here"
      }
    }
  }
}

Any MCP client that can spawn a stdio subprocess works the same way: run uv --directory /path/to/agentic-misp-mcp run agentic-misp-mcp --transport stdio (or the docker run --rm -i ... --transport stdio equivalent from Docker).

Transport note: stdio is the recommended production transport. The HTTP transport is experimental, has no built-in auth or TLS, and refuses to bind a non-loopback host unless AGENTIC_MISP_MCP_ALLOW_INSECURE_HTTP_BIND=true; if you must use it, put it behind an authenticated TLS-terminating gateway.

Production checklist

Before pointing agents at a production MISP:

  • Create a dedicated least-privilege MISP API key for this server (not a personal or site-admin key).
  • Keep AGENTIC_MISP_MCP_ROLE=read_only and AGENTIC_MISP_MCP_ENABLE_WRITE=false for normal agent use; enable writes only when a workflow genuinely needs them.
  • If writes are enabled, use AGENTIC_MISP_MCP_APPROVAL_MODE=production and keep the approval CLI and approval database out of the agent's reach.
  • Persist audit logs (AGENTIC_MISP_MCP_AUDIT_LOG_PATH; mount a volume under Docker).
  • Persist the approval store (AGENTIC_MISP_MCP_APPROVAL_STORE_PATH).
  • Protect MISP_API_KEY — environment/secrets manager only; keep .env files out of git and out of client configs that get shared.
  • Keep MISP_VERIFY_TLS=true; fix certificate problems with your internal CA, don't disable verification.
  • Run agentic-misp-mcp config-check and agentic-misp-mcp config doctor after every config change.
  • Run the test suite (uv run --extra dev pytest -q) on the deployed revision.
  • Smoke test with MCP Inspector (tools/list, then get_misp_status).
  • Review audit.jsonl after the first real tool calls, and periodically thereafter (manual audit review is the accepted control — there is no built-in alerting).
  • Keep feed administration (enable/fetch/cache) in the MISP UI/API, outside MCP.

Deeper guidance: docs/production-readiness.md, docs/production-write.md, docs/rollback.md.

Safety boundaries

These are design boundaries, enforced in code and preserved across releases:

  • No raw MISP API proxy. Only the 25 workflow tools exist; there is no generic endpoint-passthrough tool.
  • No feed mutation. No feed enable/disable/fetch/cache/edit/delete tools exist. Feed observability (list_feeds, get_feed_status, summarize_feed_health) is strictly read-only, with URLs and header/token-like fields redacted.
  • No approval-store exposure. No MCP tool can create, approve, reject, or read approval records; production approvals happen only through the operator CLI.
  • No ungated writes. Every write path goes through role policy, the write-mode gate, and the approval gate; results are explicit (blocked/pending_approval/executed/failed).
  • No hidden mutation in read tools. Read tools call read endpoints only.
  • propose_* tools are dry-run only. They build and validate payloads; they never invoke a MISP write endpoint.
  • No secret passthrough. API keys, tokens, passwords, and authorization headers are never accepted as tool arguments and are redacted from audit logs.
  • No shell execution or unrestricted filesystem tools; no user/org/server/settings admin tools.

See docs/security.md for the full security model and audit semantics.

Scoring behavior

Since v0.3.0, IOC scoring is age-aware by default. investigate_ioc, generate_ioc_report, and pivot_ioc responses include a freshness block that labels the intel behind a verdict:

Label Meaning (defaults)
fresh Newest signal ≤ 30 days old.
aging 31–90 days.
stale 91–365 days.
expired Older than 365 days.
unknown No usable timestamps found.

How it affects scores:

  • Old intel scores lower by default. Positive score factors are discounted by intel age (default weights 1.0 / 0.75 / 0.4 / 0.15 for fresh/aging/stale/expired).
  • Penalties are never age-discounted. Warninglist hits and benign-tag penalties apply at full strength regardless of age.
  • Expired intel cannot become likely_malicious on its own — expired-only intel is capped below that threshold and needs fresh corroboration to cross it.
  • AGENTIC_MISP_MCP_AGE_WEIGHTING=false restores exact v0.2.x scoring (the freshness block is still reported).

This is a confidence-quality improvement, not a replacement for analyst judgment: a fresh hit on a 10-year-old OSINT event that was recently re-published still deserves human correlation with current telemetry before blocking or escalation.

Troubleshooting

Symptom Likely cause Fix
Connection error, MISPClientError Wrong MISP_URL, or MISP unreachable from where the server runs Verify the URL (scheme + host, no trailing API path); test curl https://misp.example.local/servers/getVersion -H "Authorization: <key>" from the same host/container.
Authentication error, MISPAuthenticationError Invalid or revoked MISP_API_KEY Regenerate the automation key in MISP; confirm the env var actually reaches the process (config-check shows whether it is set, redacted).
TLS verification failure Self-signed or internal-CA certificate Add the CA to the system trust store. MISP_VERIFY_TLS=false is an isolated-lab escape hatch only — never production.
MISP returns permission denied The API key's MISP role lacks the needed permission Grant the minimal MISP permission the workflow needs (e.g. sighting creation for sightings), keeping the key least-privilege.
Tool returns blocked Policy working as intended: role or write-mode gate Check AGENTIC_MISP_MCP_ROLE and AGENTIC_MISP_MCP_ENABLE_WRITE. The audit log records outcome=blocked with the reason.
Write returns pending_approval Approval required (the default) Lab mode: re-call with approved=true (plus approval_token if configured). Production mode: an operator must approve via agentic-misp-mcp approvals ... and the call must present the resulting approval_request_id.
config-check fails on audit path Audit log directory missing or not writable Create the directory / fix permissions; under Docker, mount a writable volume at the audit path.
Approvals disappear after restart Approval DB not persisted Point AGENTIC_MISP_MCP_APPROVAL_STORE_PATH at persistent storage (Docker: a mounted volume).
"Response too large" error MISP response exceeded AGENTIC_MISP_MCP_MAX_RESPONSE_BYTES (fail-closed by design) Narrow the query (smaller limit, tighter date range). Raising the cap is a last resort.
MCP client can't spawn the server Wrong command/path in the client config Use absolute paths (uv --directory /path/to/agentic-misp-mcp ...); test the exact command in a terminal first; restart the client session after registering.
Import errors / wrong Python Wrong environment or Python < 3.11 Use uv run (which pins the project env), or re-run uv sync --extra dev; check python --version ≥ 3.11.

Release status

  • Latest release: v0.3.2 — date-validation hardening patch on v0.3.1 (search_events now rejects calendar-invalid dates like 2026-02-30; no MCP tool, scoring, write-surface, or approval-workflow changes). See CHANGELOG.md.
  • Functional baseline: v0.3.0 — age-aware scoring, six new read-only tools (sightings, event search, status, feed observability), read-tool response envelope.
  • Supported MISP baseline: 2.5.42, live-validated 14/14 — docs/live-validation-report-v0.3.0.md.
  • Latest pre-merge review findings: docs/review-v0.3.0-findings.md.
  • Tool count: 25. Tests: 358 (mocked MISP responses; live validation is a separate manual pass).
  • Scope of the production claim: v0.2.0 was declared GA for the MCP-server scope of this project only (server behavior, MISP API behavior, approval workflow, audit/redaction, config safety) — not a SIEM/SOAR/SOC platform claim. v0.3.x extends that same scope. See docs/ga-production-readiness-plan.md.
  • Known limitations: only MISP 2.5.42 is validated; a live HTTP 429 has mocked coverage only (no safe way to trigger one in the lab); container/dependency/secret scanning and signed release artifacts are not yet part of CI/release; HTTP transport is experimental; historical OSINT hits should be correlated with current telemetry (mitigated but not removed by age-aware scoring).

Development

uv run --extra dev ruff check .
uv run --extra dev ruff format --check .
uv run --extra dev pytest -q

Equivalent Make targets: make lint, make format-check, make test, make check. CI runs the same checks on Python 3.11 and 3.12.

Documentation

Contributing

Contributions are welcome, but the project boundary is not up for debate in a PR: no raw MISP API proxy, no secret passthrough, no unaudited tool path, and no write behavior that skips the policy/approval gates. Before writing code, read PROJECT_STATE.md, docs/security.md, and src/agentic_misp_mcp/tools/registry.py so your change lands inside that boundary instead of against it.

  1. Fork and branch. Fork the repository and create a feature branch off main (for example fix/search-events-date-validation or feat/short-description) — don't work directly on main.

  2. Make the change. Keep the diff scoped to one concern. If you're touching a policy-gated write tool, a scoring calculation, or anything under misp/, policy/, or audit.py, explain the reasoning in your PR description — these paths get read closely (see "Security-sensitive changes" below).

  3. Add or update tests. New behavior needs new test coverage; changed behavior needs its existing tests updated to match. Run the suite locally:

    uv run pytest -q
    
  4. Run Ruff before you push. Both lint and format are enforced in CI (.github/workflows/ci.yml) and must pass clean:

    uv run ruff check .
    uv run ruff format --check .
    

    (make check runs all three — lint, format check, and tests — in one command.)

  5. Write clear commits. Each commit should describe one change and why it was made, not just what changed — the diff already shows what changed. Squash exploratory or fixup commits before opening the PR.

  6. Open the pull request with real context. Describe the problem, the fix, and how you verified it (test output, and live-lab evidence if you ran any against a real MISP instance). State explicitly whether the change affects the MCP tool surface, scoring behavior, or the write/approval workflow — reviewers will check that claim against the diff.

Security-sensitive changes

Anything touching credential handling, the policy engine, approval workflows, audit logging, or the MISP client's write methods gets extra scrutiny before merge — that's the core of this project's safety model, not incidental code. Do not include real MISP URLs, API keys, tokens, or production event data in commits, issues, or PR descriptions; use the placeholders already used throughout this README and .env.example. If you find a security issue rather than proposing a fix, follow the reporting process in SECURITY.md instead of opening a public PR.

License

MIT.

from github.com/hdyrawan/agentic-misp-mcp

Install Agentic Misp in Claude Desktop, Claude Code & Cursor

Recommended · one command, every IDE
unyly install agentic-misp-mcp

Installs into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.

First time? Get the CLI: curl -fsSL https://unyly.org/install | sh

Or configure manually

Run in your terminal:

claude mcp add agentic-misp-mcp -- uvx --from git+https://github.com/hdyrawan/agentic-misp-mcp agentic-misp-mcp

FAQ

Is Agentic Misp MCP free?

Yes, Agentic Misp MCP is free — one-click install via Unyly at no cost.

Does Agentic Misp need an API key?

No, Agentic Misp runs without API keys or environment variables.

Is Agentic Misp hosted or self-hosted?

A hosted option is available: Unyly runs the server in the cloud, no local setup required.

How do I install Agentic Misp in Claude Desktop, Claude Code or Cursor?

Open Agentic Misp on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Agentic Misp with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All ai MCPs