Skip to main content
Glama
README.md
# ๐Ÿ•ต๏ธ maltego-mcp

> **An AI-assisted Maltego CE investigation copilot.** Build, expand, analyze, and
> report on OSINT investigation graphs through natural language โ€” exported as native
> Maltego `.mtgx` files.

![MCP](https://img.shields.io/badge/MCP-server-blue)
![Python](https://img.shields.io/badge/python-3.10%2B-green)
![License](https://img.shields.io/badge/license-MIT-lightgrey)
![Tools](https://img.shields.io/badge/tools-52-orange)
![Tests](https://img.shields.io/badge/tests-80%20passing-brightgreen)

An [MCP](https://modelcontextprotocol.io) server that turns an LLM into a
**Maltego CE investigation copilot** โ€” an AI-assisted OSINT platform built on
Maltego Community Edition's native graph format.

---

## Contents

- [How it works](#how-it-works)
- [Capabilities at a glance](#capabilities-at-a-glance)
- [Install as an MCP server (recommended)](#install-as-an-mcp-server-recommended)
- [Manual / pip install](#manual--pip-install)
- [Tools](#tools) ยท [full reference โ†’ `TOOLS.md`](TOOLS.md)
- [Transforms by provider](#transforms-by-provider)
- [Example workflows](#example-workflows)
- [Verifying a graph opens in Maltego CE](#verifying-a-graph-opens-in-maltego-ce)
- [Extending](#extending) ยท [Architecture](#architecture) ยท [Notes & limitations](#notes--limitations)

## How it works

Maltego CE has no live external API. Instead of trying to remote-control the
desktop UI, this server uses Maltego's **native `.mtgx` graph file** (a ZIP
archive of GraphML XML) as the integration surface:

1. The LLM builds / reads / edits an investigation graph held **in memory**.
2. Transforms โ€” and high-level **investigation workflows / machines** โ€” expand
   the graph (e.g. a domain โ†’ its IP addresses โ†’ open ports).
3. The LLM **analyzes** the graph (summaries, pivots, next steps), lays it out,
   and generates a shareable **report**.
4. The graph is saved as a **`.mtgx` file** that you open (or refresh) in
   Maltego CE.

A pluggable **transform-provider layer** keeps the design extensible: the
built-in `local` provider needs no API keys, and external OSINT providers
(VirusTotal, Shodan, SecurityTrails, Censys, Hunter.io, HaveIBeenPwned) activate
automatically when their API keys are present โ€” all without changing the graph
core or the MCP tools.

### Capabilities at a glance

| Area | What you get |
|------|--------------|
| **Build graphs** | Create/edit entities & links; save/open native `.mtgx`. |
| **High-level workflows** | `investigate_domain/email/ip` โ€” one call runs many transforms. |
| **Unified entry point** | `maltego_investigate(query)` โ€” detect, build, expand, analyze, recommend in one call. |
| **Investigation Memory** | Procedural memory: records *why/how* each step ran; queryable; travels in the `.mtgx`. |
| **Next Best Action** | Deterministic, explainable, memory-aware ranking of the most valuable next move. |
| **Risk & confidence** | Per-entity confidence, source reliability, linkage, priority, novelty scores. |
| **Real-time mode** | Optional event stream (entity_discovered, transform_*, report_generated, โ€ฆ). |
| **Investigation machines** | Reusable templates (Passive Domain, Email, Infrastructure Mapping). |
| **OSINT providers** | VirusTotal, Shodan, SecurityTrails, Censys, Hunter.io, HIBP (env-var keys). |
| **AI analysis** | Summarize, explain entity, identify pivots, suggest next steps. |
| **Layout** | Deterministic hierarchical / radial / force-directed layouts. |
| **CSV import** | Bulk-build graphs from `type,value` CSV. |
| **Reporting** | Deterministic Markdown / HTML investigation reports (now incl. quality scores). |
| **Continuation** | Load or merge existing `.mtgx` investigations and keep working. |

## Install as an MCP server (recommended)

This is a standalone **MCP server**. The server is launched with
[`uv`](https://docs.astral.sh/uv/) via `uvx`, which auto-installs the Python dependencies in an
isolated environment โ€” **no manual `pip install` needed**. Install `uv` once if you don't have it:

```shell
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
```

### Add it to Claude Code

Register the server straight from GitHub (available in every project โ€” user scope):

```shell
claude mcp add maltego --scope user -- uvx --from git+https://github.com/SulimanAbdulrazzaq/maltego-mcp.git maltego-mcp
```

Or run from a local clone (reflects your local edits โ€” best for development):

```shell
git clone https://github.com/SulimanAbdulrazzaq/maltego-mcp.git
claude mcp add maltego --scope user -- uvx --from ./maltego-mcp maltego-mcp
```

> On Windows PowerShell, the `--` separator can be swallowed by the shell. If `claude mcp add`
> errors with `unknown option '--from'`, add the server by editing your config instead: open
> `~/.claude.json` and add a `maltego` entry under the top-level `"mcpServers"` object:
> ```json
> "maltego": {
>   "type": "stdio",
>   "command": "uvx",
>   "args": ["--from", "git+https://github.com/SulimanAbdulrazzaq/maltego-mcp.git", "maltego-mcp"]
> }
> ```

The repo also ships a committed [`.mcp.json`](.mcp.json), so if you simply **open a clone of this
repo in Claude Code** the `maltego` server is offered automatically (project scope, launched with
`uvx --from .`).

Verify it connected:

```shell
claude mcp list   # โ†’ maltego: uvx ... - โˆš Connected
```

After it connects, the `maltego_*` tools are available in Claude. Set OSINT keys (optional) in
your shell before starting Claude Code to enable those providers (see
[Transforms by provider](#transforms-by-provider)).

> Prefer not to use `uv`? See [Manual / pip install](#manual--pip-install) and point the MCP
> command at the venv's `maltego-mcp` executable instead.

### Windows troubleshooting (first launch)

On Windows, the very first launch occasionally fails with
`failed to rename ... Access is denied (os error 5)` while unpacking `pywin32` (a transitive
dependency of `mcp`). This is **Windows Defender** briefly locking the files during real-time
scanning โ€” not a bug in the server. Fixes:

- **Just retry** โ€” restart Claude Code; it succeeds once Defender finishes scanning and the
  dependency is cached (verified: it works on the second attempt).
- Or pre-warm the cache once from a terminal: `uvx --from <path-to-this-repo> maltego-mcp`
  (Ctrl-C after it prints nothing โ€” it's a stdio server), then retry in Claude Code.
- Or add an exclusion for `%LOCALAPPDATA%\uv\cache` in Windows Security โ†’ Virus & threat
  protection โ†’ Exclusions.

## Manual / pip install

```bash
cd maltego-mcp
python -m venv .venv
.venv/Scripts/activate        # Windows
# source .venv/bin/activate   # macOS/Linux
pip install -e .
```

Then register the stdio server with any MCP client, e.g.:

```json
{
  "mcpServers": {
    "maltego": { "command": ".../.venv/Scripts/maltego-mcp.exe" }
  }
}
```

## Running

The server speaks MCP over **stdio** (ideal for local desktop integration):

```bash
maltego-mcp
# or
python -m maltego_mcp.server
```

### Register with an MCP client

Example `mcp.json` / client config entry:

```json
{
  "mcpServers": {
    "maltego": {
      "command": "C:/Users/you/Desktop/maltego_mcp/.venv/Scripts/maltego-mcp.exe"
    }
  }
}
```

(Use the `.venv` Python on macOS/Linux: `"command": ".../.venv/bin/maltego-mcp"`.)

### Test with the MCP Inspector

```bash
npx @modelcontextprotocol/inspector maltego-mcp
```

## Tools

**52 tools.** The tables below group them by area. For the **complete reference with every
argument, type, and default**, see [`TOOLS.md`](TOOLS.md) (auto-generated from the live tool
schemas โ€” the file an AI agent should read to learn the exact interface).

### Graph management
| Tool | Description |
|------|-------------|
| `maltego_create_graph` | Create a new empty in-memory graph (becomes active). |
| `maltego_open_graph` | Load an existing `.mtgx` file into memory. |
| `maltego_save_graph` | Write a graph to a `.mtgx` file for Maltego CE. |
| `maltego_list_graphs` | List open graphs and show the active one. |
| `maltego_set_active_graph` | Switch the active graph. |

### Entities & links
| Tool | Description |
|------|-------------|
| `maltego_add_entity` | Add a node (domain, IP, person, email, โ€ฆ). |
| `maltego_add_link` | Add a directed link between two entities. |
| `maltego_list_entities` | List/filter/paginate entities on the active graph. |
| `maltego_get_entity` | Full details for one entity. |
| `maltego_update_entity` | Update value/properties/notes/weight. |
| `maltego_delete_entity` | Delete an entity and its links. |
| `maltego_list_entity_types` | Discover supported Maltego entity types. |

### Transforms
| Tool | Description |
|------|-------------|
| `maltego_list_transforms` | List available transforms (optionally by input type; shows availability). |
| `maltego_run_transform` | Run a single transform on an entity and add the results. |

### High-level investigation workflows
| Tool | Description |
|------|-------------|
| `maltego_investigate_domain` | Seed a domain and auto-run all applicable/available transforms. |
| `maltego_investigate_email` | Seed an email and auto-investigate (domain, breaches, footprint). |
| `maltego_investigate_ip` | Seed an IP and auto-investigate (reverse DNS, ports, services). |
| `maltego_list_machines` | List investigation machines (workflow templates). |
| `maltego_run_machine` | Run a machine (e.g. `passive_domain`) against a seed value. |

### Unified entry point (primary interface for agents)
| Tool | Description |
|------|-------------|
| `maltego_investigate` | **One call does it all**: detect type โ†’ build/expand graph โ†’ layout โ†’ summarize โ†’ rank โ†’ next-best-actions โ†’ **inline report**, returned as one finished briefing. Supports **`depth`**: `quick` / `standard` / `deep` (deep runs *all* applicable transforms over more rounds). No follow-up calls or file writes needed. |
| `maltego_expand_entity` | Run all applicable transforms on **one** entity (pivot from a specific node). |
| `maltego_find_path` | Shortest relationship path between two entities. |
| `maltego_guide` | Returns the server's usage guidance (workflow + tool map) on demand. |

The AI is told *how* to use these tools via the server's **MCP instructions** (auto-injected
into the model's context โ€” this is how the assistant knows to run an investigation to completion
instead of asking after each step). You can also invoke the bundled command
**`/maltego-mcp:investigate <target>`** or the **`investigate` / `triage` / `report` prompts**.

### AI-oriented analysis (the "copilot")
| Tool | Description |
|------|-------------|
| `maltego_summarize_graph` | Deterministic overview: counts, type breakdown, key/isolated entities. |
| `maltego_explain_entity` | Explain one entity: data, neighbours, applicable transforms. |
| `maltego_identify_pivots` | Rank the most-connected pivot entities. |
| `maltego_suggest_next_steps` | Simple heuristic suggestions (retained for compatibility). |
| `maltego_next_best_actions` | **Decision engine**: deterministic, explainable, memory-aware ranking of the best next move. |

### Investigation Memory (procedural memory)
| Tool | Description |
|------|-------------|
| `maltego_list_investigation_steps` | List recorded steps (what ran, why, outcome, importance). |
| `maltego_explain_why` | Trace an entity's provenance โ€” which transform/step discovered it and why. |
| `maltego_explain_transform` | Full detail of one recorded transform execution (by execution id). |
| `maltego_get_investigation_timeline` | Chronological narrative of the whole investigation. |

### Risk & confidence scoring
| Tool | Description |
|------|-------------|
| `maltego_score_entity` | Confidence, source reliability, linkage strength, priority, novelty for one entity. |
| `maltego_rank_entities` | Rank all entities by investigation priority. |
| `maltego_explain_scores` | Scores plus a deterministic rationale for one entity. |

### Real-time mode (optional)
| Tool | Description |
|------|-------------|
| `maltego_subscribe_events` | Enable live event mode; returns a subscription id. |
| `maltego_get_recent_events` | Poll recent events (supports `since_seq` incremental polling). |

### Layout, CSV, import/export, link & graph management
| Tool | Description |
|------|-------------|
| `maltego_apply_layout` | Assign positions (`hierarchical`/`radial`/`force`), saved into the `.mtgx`. |
| `maltego_import_csv` | Build entities/links from a CSV file or inline CSV text. |
| `maltego_export_csv` | Export entities to CSV (round-trips with import). |
| `maltego_export_json` | Export the full graph + memory + scores as JSON. |
| `maltego_list_links` / `maltego_delete_link` | List or delete individual links. |
| `maltego_rename_graph` / `maltego_delete_graph` | Rename or drop an open graph. |
| `maltego_list_providers` | List OSINT providers and whether their API keys are configured. |
| `maltego_generate_report` / `maltego_export_report` | Markdown/HTML report inline or to a file. |
| `maltego_load_graph` / `maltego_import_graph` | Open a `.mtgx` as a new graph, or merge into the active one. |

### Outcome-based learning (opt-in)
| Tool | Description |
|------|-------------|
| `maltego_learning_stats` | View cross-investigation transform success/yield history. |
| `maltego_reset_learning` | Clear the learning store. |

Learning is **off by default** (keeps results deterministic). Enable with
`MALTEGO_MCP_LEARNING=1` (or `MALTEGO_MCP_LEARNING_PATH=/path/to/learning.json`). When on, the
server records per-transform outcomes across investigations and lets that history nudge
`maltego_next_best_actions`.

### Transforms by provider

**No API key required** โ€” work out of the box:

- `dns.domain_to_ip` โ€” domain/DNS name โ†’ IPv4 addresses (DNS A record) *[network]*
- `dns.ip_to_host` โ€” IPv4 address โ†’ hostname (reverse DNS / PTR) *[network]*
- `parse.url_to_domain` / `parse.email_to_domain` / `parse.domain_to_website` *(offline)*
- `crtsh.domain_to_subdomains` โ€” **subdomains from Certificate Transparency (crt.sh)** *[network]*
- `rdap.domain_info` โ€” **registrar, dates, nameservers, contacts (RDAP/WHOIS)** *[network]*
- `rdap.ip_info` โ€” **netblock + owning org/ASN for an IP (RDAP)** *[network]*

External OSINT providers โ€” **activate when their env-var key is set** (see
`maltego_list_providers`). Transforms are always *listed* but only *run* when
configured; a missing key yields an actionable message rather than an error.

| Provider | Env var(s) | Example transforms |
|----------|-----------|--------------------|
| VirusTotal | `VIRUSTOTAL_API_KEY` | `vt.domain_to_ip`, `vt.domain_to_subdomains`, `vt.ip_to_domain` |
| Shodan | `SHODAN_API_KEY` | `shodan.ip_to_info`, `shodan.domain_to_subdomains` |
| SecurityTrails | `SECURITYTRAILS_API_KEY` | `securitytrails.domain_to_subdomains`, `securitytrails.domain_to_dns` |
| Censys | `CENSYS_API_ID`, `CENSYS_API_SECRET` | `censys.ip_to_services` |
| Hunter.io | `HUNTER_API_KEY` | `hunter.domain_to_emails` |
| Have I Been Pwned | `HIBP_API_KEY` | `hibp.email_to_breaches` |

Configure keys via environment variables (in your MCP client's `env` block or
the shell), then restart the server. Example client config:

```json
{
  "mcpServers": {
    "maltego": {
      "command": ".../.venv/Scripts/maltego-mcp.exe",
      "env": { "VIRUSTOTAL_API_KEY": "...", "SHODAN_API_KEY": "..." }
    }
  }
}
```

## Example workflows

**Manual (low-level):**
```
maltego_create_graph(name="acme-recon")
maltego_add_entity(type="maltego.Domain", value="example.com")        # -> n0
maltego_run_transform(transform_name="dns.domain_to_ip", entity_id="n0")
maltego_apply_layout(algorithm="hierarchical")
maltego_save_graph(path="C:/Users/you/Desktop/acme-recon.mtgx")
```

**One-call copilot (recommended for agents):**
```
maltego_investigate(query="bob@example.com")   # detect โ†’ build โ†’ expand โ†’ analyze โ†’ recommend
maltego_explain_why(entity_id="n1")            # why is this entity here?
maltego_next_best_actions()                    # explainable, memory-aware ranking
maltego_rank_entities()                        # focus on the highest-priority findings
maltego_get_investigation_timeline()           # the reasoning trace
maltego_generate_report(format="html")
maltego_save_graph(path="C:/cases/example.mtgx")   # memory travels inside the .mtgx
```

**AI-assisted (step-by-step):**
```
maltego_investigate_domain(value="example.com")     # auto-runs transforms
maltego_identify_pivots()                            # find key nodes
maltego_next_best_actions()                          # what to do next (decision engine)
maltego_apply_layout(algorithm="radial")
maltego_generate_report(format="markdown")           # shareable report
maltego_save_graph(path="C:/Users/you/Desktop/example.mtgx")
```

**Continue a previous investigation:**
```
maltego_load_graph(path="C:/cases/old.mtgx")         # reopen
maltego_run_machine(machine_name="infrastructure_mapping", seed_value="example.com")
maltego_import_graph(path="C:/cases/related.mtgx")   # merge in another case
```

**Bulk import from CSV:**
```
maltego_import_csv(content="type,value,link_to\nDomain,example.com,\nIPv4Address,1.2.3.4,example.com\n")
```

## Extending

### Add a new OSINT provider

1. Create a module under `src/maltego_mcp/transforms/osint/`.
2. Write pure parser functions (`dict -> list[ResultEntity]`) and async `run`
   functions that read the API key from an env var via `require_keys(...)`.
3. Register a `ProviderInfo` with `providers.register(...)` and your
   `Transform(...)` objects (with `api_key_env=...`) via `registry.register(...)`.
4. Import the module from `transforms/osint/__init__.py`.

No changes to the graph core, orchestration, machines, or MCP tools are needed โ€”
new transforms automatically participate in `investigate_*`, machines, analysis,
and suggestions.

### Add an investigation machine

```python
from maltego_mcp.machines import Machine, register_machine
register_machine(Machine(
    name="my_workflow", display_name="My Workflow", description="...",
    seed_type="maltego.Domain",
    transform_names=["dns.domain_to_ip", "vt.domain_to_subdomains"],
    allow_network=True, max_rounds=2,
))
```

## Architecture

```
src/maltego_mcp/
โ”œโ”€โ”€ server.py          # FastMCP server (with MCP instructions) + 52 tools + prompts
โ”œโ”€โ”€ models.py          # Pydantic input models
โ”œโ”€โ”€ entities.py        # Maltego entity-type catalog
โ”œโ”€โ”€ formatting.py      # markdown/JSON response helpers + error mapping
โ”œโ”€โ”€ detect.py          # query -> entity type/value/machine (for maltego_investigate)
โ”œโ”€โ”€ orchestration.py   # breadth-first engine + run_and_record (memory+events choke-point)
โ”œโ”€โ”€ machines.py        # reusable workflow templates + registry
โ”œโ”€โ”€ analysis.py        # deterministic summarize/explain/pivots/next-steps
โ”œโ”€โ”€ recommendation.py  # Next Best Action decision engine (memory-aware, explainable)
โ”œโ”€โ”€ scoring.py         # Risk & confidence engine (deterministic per-entity metrics)
โ”œโ”€โ”€ memory.py          # Investigation Memory (procedural memory; storage + queries)
โ”œโ”€โ”€ learning.py        # opt-in cross-investigation outcome learning (feeds NBA)
โ”œโ”€โ”€ events.py          # architecture-agnostic event bus (real-time mode)
โ”œโ”€โ”€ layout.py          # hierarchical / radial / force-directed layouts
โ”œโ”€โ”€ csv_import.py      # CSV -> entities/links (type aliases, dedupe)
โ”œโ”€โ”€ reporting.py       # deterministic Markdown / HTML reports (incl. quality scores)
โ”œโ”€โ”€ graph/
โ”‚   โ”œโ”€โ”€ graph_store.py # in-memory Graph (+ .memory, merge, analysis helpers)
โ”‚   โ”œโ”€โ”€ mtgx_writer.py # Graph -> .mtgx (GraphML + positions + memory sidecar + zip)
โ”‚   โ””โ”€โ”€ mtgx_reader.py # .mtgx -> Graph (recovers positions + memory sidecar)
โ””โ”€โ”€ transforms/
    โ”œโ”€โ”€ base.py        # Transform/registry + ProviderInfo/ProviderRegistry (+ reliability)
    โ”œโ”€โ”€ local.py       # built-in no-auth transforms
    โ””โ”€โ”€ osint/         # providers
        โ”œโ”€โ”€ base_http.py
        โ”œโ”€โ”€ keyless.py    # NO-key: crt.sh (cert transparency), RDAP (domain + IP)
        โ””โ”€โ”€ virustotal.py, shodan.py, securitytrails.py, censys.py, hunterio.py, hibp.py
```

### Investigation Memory & determinism

* **Procedural memory** (`memory.py`) records every transform execution โ€” the
  trigger entity, the chosen transform, *why* it was chosen, what it discovered,
  status, importance, and whether to reconsider it. It is stored on
  `Graph.memory`, kept *separate from the graph structure*, and serialized to a
  sidecar member (`maltego_mcp/investigation_memory.json`) inside the `.mtgx` โ€”
  so it travels with the investigation but never affects Maltego CE
  compatibility (Maltego ignores unknown archive members).
* `orchestration.run_and_record` is the single choke-point through which the
  engine *and* the manual `maltego_run_transform` tool execute transforms, so
  memory and events are captured consistently everywhere.
* **Scores** (`scoring.py`) are computed deterministically from the graph + memory
  and provider reliability (`ProviderInfo.reliability`), so the same investigation
  always yields the same scores, recommendations, and reports.

## Verifying a graph opens in Maltego CE

The `.mtgx` format is validated by our reader/writer round-trip and by checking entity
property field names against Maltego's real definitions (e.g. `Domain`/`Website` โ†’ `fqdn`,
`Company`/`Organization` โ†’ `title`, `IPv4Address` โ†’ `ipv4-address`). To confirm end-to-end in
the actual app:

1. Install **Maltego CE** (free; requires a download + account at maltego.com).
2. Generate a sample: `maltego_investigate("example.com")` (or add a few entities) then
   `maltego_save_graph(path="โ€ฆ/sample.mtgx")`. A ready-made `sample-verification.mtgx` is
   produced on the Desktop by the test fixtures.
3. In Maltego CE: **File โ†’ Import โ†’ Import Graph** (or File โ†’ Open) and select the `.mtgx`.
4. Confirm entities render **with their values populated**, correct types, and links with
   labels. If a given type's value is blank, its `main_property` in `src/maltego_mcp/entities.py`
   needs correcting against Maltego's field id for that entity.

> Status: the common entity types (Domain, IP, Email, Website, Person, Company, โ€ฆ) have had
> their field names verified against a reference; opening in a real Maltego CE install is the
> final confirmation step and is left to the user (no Maltego install was available here).

## Notes & limitations

- Targets Maltego CE's file format; it does **not** remote-control the running
  desktop app. Re-open or refresh the `.mtgx` in Maltego after saving.
- The entity-type catalog is a curated subset; custom `maltego.*` types are
  accepted and saved as-is.
- Graphs live in process memory until saved; restarting the server clears unsaved
  graphs.
- Layout positions are written into the `.mtgx` as yFiles node graphics. Maltego
  CE may re-run its own layout on import; positions are always available via the
  tools regardless.
- OSINT provider transforms call third-party APIs โ€” respect each provider's terms
  of service and rate limits. Without a key, those transforms are listed but skip
  with a clear "missing credential" message.
- Reports, layouts, scores, and recommendations are **deterministic**: the same
  graph + memory always yields the same output, so results are reproducible and
  shareable. (Timestamps in memory/events are the only non-deterministic field.)
- **Investigation Memory** is stored as a sidecar JSON member inside the `.mtgx`
  and is recovered on load โ€” it survives save/load and merges, and is ignored by
  Maltego CE. Manually-added/CSV entities are "analyst-provided" (no discovering
  step) and scored with full source reliability.
- **Real-time mode** is optional: the event bus always buffers cheaply, and
  `maltego_subscribe_events` enables live callbacks. Over MCP stdio you retrieve
  events by polling `maltego_get_recent_events` (use `since_seq` for increments).

## License

MIT

TDQS

A4/5.0

Scored across 52 tools

Disambiguation4/5

Most tools have clearly distinct purposes, especially with detailed descriptions. However, there is some overlap between the generic 'maltego_investigate' and the type-specific 'maltego_investigate_domain', 'maltego_investigate_email', 'maltego_investigate_ip', and between 'maltego_suggest_next_steps' and 'maltego_next_best_actions', which could cause confusion.

Naming Consistency5/5

All tools follow a consistent 'maltego_' prefix with snake_case naming. Verbs are uniform and descriptive (e.g., list_*, create_*, delete_*), and compound names like 'investigate_domain' follow a predictable pattern.

Tool Count3/5

52 tools is a large number for an MCP server, bordering on excessive. While the domain is complex, many tools (e.g., type-specific investigates, legacy 'suggest_next_steps') could be consolidated, making the surface feel heavy.

Completeness4/5

The tool set covers the full investigation lifecycle: graph management, entity/link CRUD, transforms, analysis, scoring, reporting, and learning. Minor gaps exist (e.g., no tool to clear all entities), but overall it is comprehensive.

Maintenance

ActivityInactive
ResponsivenessNo issues