misp-mcp

misp-mcp

Connects MISP to MCP clients, enabling threat indicator lookups and submissions in plain language.

Category
Visit Server

README

<p align="center"> <picture> <source media="(prefers-color-scheme: light)" srcset="assets/banner-light.svg"> <img src="assets/banner-dark.svg" alt="MISP MCP - Malware Information Sharing Platform" width="820"> </picture> </p>

<p align="center"> Ask about a threat indicator in plain language and get an answer from MISP. </p>

<p align="center"> <img src="https://img.shields.io/badge/version-1.4.0-informational" alt="version 1.4.0"> <img src="https://img.shields.io/badge/license-Apache--2.0-lightgrey" alt="license Apache-2.0"> <img src="https://img.shields.io/badge/python-3.10%2B-informational" alt="Python 3.10+"> <img src="https://img.shields.io/badge/tests-65%20passing-lightgrey" alt="65 tests passing"> </p>


misp-mcp connects MISP to any MCP client (Claude Desktop, Claude Code, Cursor, and others). You ask in plain language, the client calls MISP, you get the answer. No MISP UI, no REST calls by hand. Nineteen tools read from MISP - indicators, events, feeds, the galaxy / taxonomy / tag knowledge base, warninglist checks, and worker/job health - and two add indicators (single + bulk), all under your own MISP key.


Connect to the hosted server

The server runs at https://misp.example.com/mcp. There is nothing to install; point your MCP client at it with your own MISP key. You must be on the your corporate network or VPN (the endpoint is not on the public internet).

1. Get your MISP key (one time)

  1. Open https://misp.example.com and log in.
  2. Top-right menu → My Profile → Auth Keys → Add authentication key.
  3. Comment it misp-mcp <your-name>, then copy the key - MISP shows it once. A read-only key is enough for lookups.

Keep the key private - every query runs as you.

2. Connect your MCP client

This is a standard remote MCP server over streamable HTTP, so any MCP-capable client works - Claude Desktop, Claude Code, Cursor, Windsurf, Cline, Continue, Zed, VS Code (Copilot/MCP), Goose, and others. Whatever the client, it needs the same three things:

  1. Transport: HTTP (streamable HTTP / remote MCP)
  2. URL: https://misp.example.com/mcp
  3. Two headers: X-MISP-Key: YOUR_KEY_HERE and X-MISP-User: you@example.com

Generic config - most clients read a JSON block like this (the key names vary slightly by client - mcpServers, servers, or mcp.servers; check your client's docs, the values are identical):

{
  "mcpServers": {
    "misp": {
      "type": "http",
      "url": "https://misp.example.com/mcp",
      "headers": {
        "X-MISP-Key": "YOUR_KEY_HERE",
        "X-MISP-User": "you@example.com"
      }
    }
  }
}

<details> <summary><b>Per-client examples</b></summary>

Claude Code (one command in a terminal):

claude mcp add --transport http misp https://misp.example.com/mcp \
  --scope user \
  --header "X-MISP-Key: YOUR_KEY_HERE" \
  --header "X-MISP-User: you@example.com"

Claude Desktop / Cursor / Windsurf - add the generic mcpServers block above to the client's MCP JSON config, then fully restart the app.

VS Code (Copilot MCP) - in .vscode/mcp.json or user settings, under "servers":

{
  "servers": {
    "misp": {
      "type": "http",
      "url": "https://misp.example.com/mcp",
      "headers": {
        "X-MISP-Key": "YOUR_KEY_HERE",
        "X-MISP-User": "you@example.com"
      }
    }
  }
}

Cline / Continue / Zed / Goose and other clients - use the same URL, http transport, and the two headers, in whatever config format the client uses. Anything that speaks remote MCP over HTTP and can send custom headers will work; the two X-MISP-* headers are the only server-specific part.

Any client that cannot send custom HTTP headers is not supported (the key must ride in X-MISP-Key).

</details>

3. Check it works

Reachability check (client-agnostic) - should print 401, which proves you can reach the endpoint and that auth is required:

curl -s -o /dev/null -w '%{http_code}\n' -X POST https://misp.example.com/mcp

If your client has a way to list MCP servers, confirm misp shows connected (Claude Code: claude mcp listmisp ... ✓ Connected; other clients show it in their MCP/tools panel).

Then ask your assistant these - if they answer from MISP, you're set:

Ask this You should get
Is MISP healthy? reachable, MISP + server version
Look up 102.130.113.9 in MISP. hits (Tor / DDoS), detection-flagged
Look up 45.9.148.99 in MISP. "not seen in MISP" (not "safe")
Triage these against MISP: 8.8.8.8, evil.com, <a hash> per-indicator verdicts

Not working?

  • 401 / timeout when asking → you're not on your network / VPN.
  • claude mcp list not "Connected" → re-check the key and headers.
  • Tools missing, stale, or the assistant says "no such tool" → reconnect (below).

Reconnect / restart it

MCP clients cache the tool list when they connect. If the server stops responding, shows the wrong tools, or was updated, the fix in every client is the same: fully quit and reopen the app (not just the conversation or window - an in-app /mcp reconnect or a new chat is often not enough). If tools are still stale, remove the misp server from the config, save, reopen, add it back, and reopen again.

New tools added on the server only appear after this full restart.

<details> <summary><b>Claude Code re-register</b></summary>

claude mcp remove misp
claude mcp add --transport http misp https://misp.example.com/mcp \
  --scope user \
  --header "X-MISP-Key: YOUR_KEY_HERE" \
  --header "X-MISP-User: you@example.com"

Then quit Claude Code completely and reopen it. Check with claude mcp listmisp ... ✓ Connected, and /mcp shows the current tools.

</details>


What you can ask

"Look up 102.130.113.9 in MISP."
"Triage these 30 IOCs from the report."
"What else showed up in the same event as evil[.]com?"
"Review the last 30 days of IOC submissions - who added what."
"Is MISP healthy? How many feeds are on?"

Behind the scenes the client calls a tool and gets structured JSON, e.g. for a lookup:

{
  "ioc": "102.130.113.9",
  "ioc_type": "ipv4",
  "total_hits": 6,
  "summary": {
    "seen_in_misp": true,
    "event_count": 6,
    "detection_flagged": true,
    "max_threat_level": "Medium",
    "restricted_hits": 0
  },
  "hits": [
    { "event_id": "16989", "event_info": "Tor exit nodes feed",
      "attribute_type": "ip-dst", "value": "102.130.113.9",
      "to_ids": true, "restricted": false }
  ]
}

Tools

Tool What it does
misp_lookup_ioc read Sightings of one IPv4/IPv6, domain, URL, or hash, with a verdict
misp_lookup_iocs read Triage many indicators in one call
misp_correlate_ioc read Other indicators in the same event, for pivoting
misp_get_event read One event: info, tags, attributes
misp_search_events read Search events by title, tag, or date
misp_feed_stats read How many feeds exist and which are on
misp_instance_status read Reachability + auth check; run first when a tool fails
misp_review_submissions read Audit recent submissions: what was added, by whom, what's detection-flagged
misp_lookup_galaxy read Threat actors, malware, tools, ATT&CK techniques by name or synonym
misp_list_galaxies read Galaxy types available on the instance
misp_list_taxonomies read Taxonomies (TLP, kill-chain, PAP) and whether each is enabled
misp_get_taxonomy read One taxonomy's tags and their meanings
misp_search_tags read Find tag definitions by name
misp_get_object read One MISP object (grouped attributes, e.g. a file object)
misp_get_attribute read One attribute by id, with its event
misp_search_attributes read Search attributes by type, category, tag, to_ids, or event (paginated)
misp_check_warninglist read Flag IOCs that hit known-good / noise lists (false-positive control)
misp_worker_status read Background worker / queue health (admin key)
misp_jobs read Recent background jobs + failures and why (admin key)
misp_submit_ioc write Add a new indicator (needs a write-capable key)
misp_submit_iocs write Bulk: validate + add many indicators (dry-run preview first)

Paste indicators however you have them - defanged forms (1.2.3[.]4, hxxp://evil[.]com) are cleaned up automatically. Private/reserved IPs are rejected (not routable, can't identify an external threat).

Security

  • Your key is the authorization. MISP checks it on every call and attributes the action to you. A read-only key cannot write; only write-capable keys (the security team) can add indicators.
  • Guarded write path. Submissions are rate-limited, well-known / first-party infrastructure can never be submitted, and the submitter is read from MISP itself - not a value the caller sets (so misp_review_submissions shows who actually added each IOC).
  • MISP content is data, not instructions. Don't submit an indicator from a lookup without checking it yourself.
  • Keys stay private. No shared key on the server; the key rides in a header over TLS. Logs never contain keys or IOC values.

Architecture

The shape is the same on any host: callers reach misp-mcp over HTTPS through a TLS-terminating load balancer (or the process's own cert), and misp-mcp calls your MISP. It holds no credential of its own - every request carries the caller's own X-MISP-Key, which MISP validates and attributes to that user.

  MCP client  (any client, on an allowed network / VPN)
       │
       │  HTTPS  +  header  X-MISP-Key: <your key>
       ▼
  Load balancer            TLS termination · ingress limited to allowed CIDRs
       │  HTTP :8080  (private)
       ▼
  misp-mcp                 container / VM, no stored secret
       │  HTTPS
       ▼
  your MISP instance
  • TLS terminates at the load balancer; misp-mcp serves plain HTTP on :8080 behind it (or give the process its own cert, see DEPLOY.md).
  • Ingress is scoped to your caller networks; the endpoint is not public.
  • Two common topologies: run misp-mcp standalone in front of a separate MISP (the Terraform module below), or co-locate it beside an existing MISP behind one load balancer with a /mcp* path rule so MISP is untouched.

Host it (local, self-host, or cloud)

  • Docker (fastest): run the published image against your own MISP.
    docker run -d -p 127.0.0.1:8080:8080 \
      -e MCP_TRANSPORT=http -e MCP_HOST=0.0.0.0 \
      -e MISP_URL=https://misp.example.com \
      -e MISP_MCP_ALLOW_INSECURE_BIND=true \
      ghcr.io/indranilroy99/misp-mcp:latest
    # or: MISP_URL=https://misp.example.com docker compose up -d
    
    Bind stays on localhost; front it with your own TLS proxy for remote use (the key is a bearer credential).
  • Local (in your MCP client, against your own MISP): install and add the misp-mcp binary - see ONBOARDING.md.
  • Self-host for a team (HTTP server behind TLS, EC2/VM + systemd): DEPLOY.md.
  • Cloud, any provider (AWS / GCP / Azure guidance): CLOUD.md.
  • AWS, Terraform - ready modules behind an internal ALB with TLS, in two flavors sharing one networking module: Fargate (serverless, no VM) or EC2 (managed VM, SSM access): deploy/terraform/. Fill in a .tfvars, terraform apply, and it prints the /mcp endpoint.

Automated local setup (from source):

git clone https://github.com/indranilroy99/misp-mcp.git
cd misp-mcp
./install.sh

<details> <summary><b>All settings</b></summary>

Setting Mode Default Meaning
MISP_URL both required MISP base URL
MISP_API_KEY local required your key (local mode)
MCP_TRANSPORT both stdio stdio for local, http for hosted
MCP_HOST hosted 127.0.0.1 bind address
MCP_PORT hosted 8080 port
MISP_VERIFY_TLS both true set false only for a self-signed lab
MISP_MCP_SHOW_RESTRICTED both true false turns on server-side TLP hiding
MISP_SUBMISSION_EVENT_ID both required for writes event that misp_submit_ioc writes to
MISP_MCP_PROTECTED_DOMAINS both empty your own domains that can never be submitted
MISP_MCP_SUBMIT_RATE both 20 max submissions per key per minute
MISP_MCP_TLS_CERT / MISP_MCP_TLS_KEY hosted none serve HTTPS directly
MISP_MCP_ALLOW_INSECURE_BIND hosted false allow a public plain-HTTP bind (TLS on a proxy)

</details>

<details> <summary><b>Development</b></summary>

python3 -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/python -m pytest tests/ -q            # 65 tests
misp_mcp/
  server.py      the 21 tools and the MCP server
  client.py      talks to the MISP REST API (read + write)
  config.py      reads settings from the environment
  http_app.py    hosted mode: header auth + web server
  context.py     carries your identity through one request
  validators.py  cleans, checks, and safelists indicators

Dependencies are pinned in pyproject.toml: mcp, httpx, pydantic, uvicorn, starlette.

</details>

<details> <summary><b>Security reporting & license</b></summary>

Report vulnerabilities privately - see SECURITY.md. Licensed under Apache-2.0 (LICENSE). Contributions welcome - see CONTRIBUTING.md.

</details>

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured