Metadata-Version: 2.3
Name: igsight-mcp
Version: 0.2.0
Summary: MCP server to read and analyze Instagram posts and profiles for AI agents
Author: Vinícius Hugenthobler
License: MIT
Requires-Dist: fastmcp>=2.0.0
Requires-Dist: httpx>=0.28.0
Requires-Dist: instaloader>=4.14
Requires-Dist: pydantic>=2.10
Requires-Dist: yt-dlp>=2025.1
Requires-Dist: faster-whisper>=1.1.0 ; extra == 'local'
Requires-Python: >=3.11
Project-URL: Homepage, https://github.com/vinihuge/igsight-mcp
Project-URL: Repository, https://github.com/vinihuge/igsight-mcp
Project-URL: Issues, https://github.com/vinihuge/igsight-mcp/issues
Provides-Extra: local
Description-Content-Type: text/markdown

# igsight-mcp

MCP server to read and analyze Instagram posts and profiles for AI agents.

Inspired by [smorand/mcp-instagram](https://github.com/smorand/mcp-instagram) (MIT). See [NOTICE](NOTICE) for attribution details.

PyPI: [igsight-mcp](https://pypi.org/project/igsight-mcp/)

## Quickstart

### Prerequisites

| Requirement | Notes |
| --- | --- |
| **Python ≥ 3.11** | Matches `requires-python` in the package |
| **ffmpeg** and **ffprobe** | On your `PATH`; needed for video/reel frame sampling and audio extraction |
| **Transcription (optional)** | Cloud: `IGSIGHT_TRANSCRIBE_*` (Groq, OpenAI, or compatible APIs). Local: install `igsight-mcp[local]` and use `faster-whisper` (see below) |

Install ffmpeg from your OS package manager (for example `brew install ffmpeg`, `apt install ffmpeg`, or [ffmpeg.org](https://ffmpeg.org/download.html)).

### Run the server

The default MCP transport is **stdio** (what Claude Desktop, Cursor, and Grok Bot expect). You can also run **streamable HTTP** for remote clients or Docker (see [HTTP transport](#http-transport) and [Docker](#docker)).

```bash
uvx igsight-mcp                  # stdio (default)
uvx igsight-mcp --transport http # streamable HTTP on 127.0.0.1:8000
```

From a git checkout:

```bash
uvx --from . igsight-mcp
```

**Local Whisper (no API key):** install the optional extra, then set `IGSIGHT_TRANSCRIBE_BACKEND=faster_whisper` (or `auto` when API vars are unset):

```bash
uv pip install 'igsight-mcp[local]'   # or: uv sync --extra local
```

### Verify setup

After configuring your MCP client, call **`check_auth`** (no arguments). It reports cookie file status, ffmpeg, transcription config, cache paths, and built-in rate limits—**without returning secret values** (API keys and cookie contents are never echoed).

Fix any items in `warnings` (for example missing cookies file, loose file permissions, or datacenter IP hints) before calling **`get_post`**.

Example first **`get_post`** prompt in your client:

> Use the get_post tool on `https://www.instagram.com/p/SHORTCODE/` with default settings.

## MCP client configuration

Use the same command everywhere:

```json
"command": "uvx",
"args": ["igsight-mcp"]
```

Add an **`env`** block for `IGSIGHT_*` variables (paths shown are examples—adjust for your machine).

### Shared `env` example

```json
"env": {
  "IGSIGHT_COOKIES_FILE": "/home/you/.config/igsight/cookies.txt",
  "IGSIGHT_CACHE_DIR": "/home/you/.cache/igsight-mcp",
  "IGSIGHT_CACHE_TTL": "3600",
  "IGSIGHT_TRANSCRIBE_BASE_URL": "https://api.groq.com/openai/v1",
  "IGSIGHT_TRANSCRIBE_API_KEY": "your-api-key-here",
  "IGSIGHT_TRANSCRIBE_MODEL": "whisper-large-v3-turbo"
}
```

Transcription is optional; omit the three `IGSIGHT_TRANSCRIBE_*` keys to skip speech-to-text.

### Claude Desktop

Edit **`claude_desktop_config.json`**:

| OS | Path |
| --- | --- |
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |

```json
{
  "mcpServers": {
    "igsight": {
      "command": "uvx",
      "args": ["igsight-mcp"],
      "env": {
        "IGSIGHT_COOKIES_FILE": "/home/you/.config/igsight/cookies.txt"
      }
    }
  }
}
```

Restart Claude Desktop after saving.

### Cursor

**Project** (repository root): `.cursor/mcp.json`

**Global**: `~/.cursor/mcp.json` (macOS/Linux) or `%USERPROFILE%\.cursor\mcp.json` (Windows)

```json
{
  "mcpServers": {
    "igsight": {
      "command": "uvx",
      "args": ["igsight-mcp"],
      "env": {
        "IGSIGHT_COOKIES_FILE": "/home/you/.config/igsight/cookies.txt"
      }
    }
  }
}
```

Reload MCP servers from Cursor settings after editing.

### Grok Bot

In Grok Bot MCP settings, add a **stdio** server with command **`uvx`**, arguments **`["igsight-mcp"]`**, and the same **`env`** keys as above (UI labels vary; the transport is stdio JSON-RPC).

### Generic stdio MCP JSON

```json
{
  "mcpServers": {
    "igsight": {
      "command": "uvx",
      "args": ["igsight-mcp"],
      "env": {
        "IGSIGHT_COOKIES_FILE": "/path/to/cookies.txt",
        "IGSIGHT_CACHE_DIR": "/path/to/cache",
        "IGSIGHT_CACHE_TTL": "3600",
        "IGSIGHT_TRANSCRIBE_BASE_URL": "https://api.openai.com/v1",
        "IGSIGHT_TRANSCRIBE_API_KEY": "sk-...",
        "IGSIGHT_TRANSCRIBE_MODEL": "whisper-1"
      }
    }
  }
}
```

## Tools

| Tool | Inputs | Outputs |
| --- | --- | --- |
| **`health_check()`** | _(none)_ | `status` (`"ok"`), `version` (package version string), `message` (short status text) |
| **`get_post(url, max_frames=6, transcribe=True)`** | `url` — Instagram post or reel URL (or shortcode forms resolved by the server). `max_frames` — key frames for video/reel (clamped to **1–20**; out-of-range values adjust with a **warning**). `transcribe` — when `true`, attempt speech-to-text on video/reel if transcription env is configured. | **Structured content:** `kind` (`photo` \| `carousel` \| `video` \| `reel`), `shortcode`, `author`, `caption`, `hashtags`, `mentions`, `timestamp`, `local_paths`, `warnings`, optional `likes`, `comments_count`. **Video/reel extras:** `duration`, `transcript` (`text`, `language`, `segments[]` with `start`/`end`/`text`) when transcription succeeds. **Content blocks:** JPEG **`ImageContent`** for each carousel slide or sampled frame. Partial failures (download, ffmpeg, transcription) append human-readable strings to **`warnings`** without failing the whole tool when possible. |
| **`analyze_profile(handle, n=12, transcribe_top_reels=0)`** | `handle` — `@username` or profile URL. `n` — recent posts to analyze (clamped to **1–50**). `transcribe_top_reels` — when **1–3**, transcribe speech on that many top-engagement reels among the analyzed posts (requires ffmpeg + a configured transcription backend). | Profile fields: `username`, `full_name`, `bio`, `external_url`, `verified`, `followers`, `following`, `posts_count`. Analytics: `posts`, `mix`, `posting_frequency`, `engagement`, `top_posts`, `recurring_hashtags`, `recurring_keywords`, `first_caption_lines`, optional `top_reels_transcripts` (shortcode, engagement, transcript payload), `warnings`. |
| **`get_comments(url, limit=50)`** | `url` — post, reel, or IGTV URL/shortcode. `limit` — comments to return (clamped to **1–200**). | `comments` (username, text, timestamp, likes, etc.) and `warnings`. **Requires** `IGSIGHT_COOKIES_FILE` (logged-in session). |
| **`download_media(url, audio_only=False)`** | `url` — post or reel URL/shortcode. `audio_only` — when `true`, extract one MP3 from video/reel instead of saving video files. | `kind`, absolute `local_paths` under the cache media directory, and `warnings`. Carousel downloads are capped (see implementation). |
| **`check_auth()`** | _(none)_ | `cookies_loaded`, `cookies_file` (path only, or `null`), `cookies_valid` (`true`/`false`/`null`), `ffmpeg_available`, `transcription_backend`, `transcription_configured`, `cache_dir`, `cache_ttl_seconds`, `rate_limit` (built-in limiter settings), `warnings`. Never includes API keys or cookie values. |

## Environment variables

All configuration uses **`IGSIGHT_*`** environment variables (there is no separate config file). Defaults match the implementation in `src/igsight_mcp/core/`.

| Variable | Default | Description |
| --- | --- | --- |
| **`IGSIGHT_COOKIES_FILE`** | _(unset)_ | Path to a Netscape-format cookies file. Optional for many public posts; recommended for reliable access. See [docs/cookies.md](docs/cookies.md). |
| **`IGSIGHT_CACHE_DIR`** | `~/.cache/igsight-mcp` | Root directory for JSON caches (posts, transcripts, `get_post` media metadata). |
| **`IGSIGHT_CACHE_TTL`** | `3600` | Cache entry lifetime in seconds. Invalid values fall back to `3600`. `0` disables TTL reads (effectively no cache reuse). |
| **`IGSIGHT_TRANSCRIBE_BASE_URL`** | _(empty)_ | OpenAI-compatible API base URL, without trailing slash. Required with API key and model to enable transcription. |
| **`IGSIGHT_TRANSCRIBE_API_KEY`** | _(empty)_ | Bearer token for the transcription API. Never logged or returned by **`check_auth`**. |
| **`IGSIGHT_TRANSCRIBE_MODEL`** | _(empty)_ | Model id for `/audio/transcriptions`. |
| **`IGSIGHT_TRANSCRIBE_BACKEND`** | `openai_compatible` | Transcription backend: `openai_compatible`, `faster_whisper`, or `auto` (API when `IGSIGHT_TRANSCRIBE_*` is complete, otherwise local faster-whisper when `igsight-mcp[local]` is installed). |
| **`IGSIGHT_WHISPER_MODEL`** | `small` | faster-whisper model size/name when using the local backend. |
| **`IGSIGHT_WHISPER_DEVICE`** | `auto` | Device for local Whisper: `auto`, `cpu`, or `cuda` (CPU uses int8 compute). |

There are **no** `IGSIGHT_*` rate-limit overrides; limits are fixed in code and reported by **`check_auth`** under `rate_limit`:

| Field | Default |
| --- | --- |
| `min_interval_seconds` | `3.0` |
| `max_interval_seconds` | `5.0` |
| `hourly_budget` | `200` |
| `bucket_capacity` | `1.0` |
| `refill_seconds` | `4.0` |

### Transcription examples

**Groq**

```json
"IGSIGHT_TRANSCRIBE_BASE_URL": "https://api.groq.com/openai/v1",
"IGSIGHT_TRANSCRIBE_API_KEY": "gsk_...",
"IGSIGHT_TRANSCRIBE_MODEL": "whisper-large-v3-turbo"
```

**OpenAI**

```json
"IGSIGHT_TRANSCRIBE_BASE_URL": "https://api.openai.com/v1",
"IGSIGHT_TRANSCRIBE_API_KEY": "sk-...",
"IGSIGHT_TRANSCRIBE_MODEL": "whisper-1"
```

Alternative OpenAI model example: `gpt-4o-mini-transcribe` (if your account exposes it on the same API).

All three transcription variables must be set together for the OpenAI-compatible backend; otherwise video/reel posts still return frames but add a transcription warning (unless local faster-whisper is selected).

**Local faster-whisper**

```json
"IGSIGHT_TRANSCRIBE_BACKEND": "faster_whisper",
"IGSIGHT_WHISPER_MODEL": "small",
"IGSIGHT_WHISPER_DEVICE": "auto"
```

Install `igsight-mcp[local]` in the same environment as the server. With `IGSIGHT_TRANSCRIBE_BACKEND=auto`, the server uses the API when all three `IGSIGHT_TRANSCRIBE_*` vars are set, otherwise local Whisper when the extra is installed.

## Third-party plugins

Install separate Python packages that declare setuptools entry points in group `igsight_mcp.plugins`. They can add MCP tools without forking the core server. Control loading with `IGSIGHT_DISABLE_PLUGINS` and `IGSIGHT_PLUGINS`. See **[docs/plugins.md](docs/plugins.md)** and **`examples/igsight-plugin-hello/`**.

## HTTP transport

For MCP clients that speak **streamable HTTP** instead of stdio:

| Variable / flag | Default | Purpose |
| --- | --- | --- |
| `--transport http` or `IGSIGHT_TRANSPORT=http` | `stdio` | Enable HTTP transport |
| `--host` / `IGSIGHT_HOST` | `127.0.0.1` | Bind address |
| `--port` / `IGSIGHT_PORT` | `8000` | Listen port |
| `IGSIGHT_HTTP_TOKEN` | _(unset)_ | When set, requires `Authorization: Bearer <token>` on every HTTP request |

```bash
export IGSIGHT_HTTP_TOKEN="$(openssl rand -hex 32)"
uvx igsight-mcp --transport http --host 127.0.0.1 --port 8000
```

Binding to a non-loopback address prints a security warning; always set `IGSIGHT_HTTP_TOKEN` when the port is reachable from other machines.

## Cookies

See **[docs/cookies.md](docs/cookies.md)** for exporting Netscape `cookies.txt`, `chmod 600`, secondary accounts, and keeping cookies out of git.

## Account safety and rate limits

**igsight-mcp** is built for **occasional, read-only** agent use—not bulk scraping.

- **Built-in rate limiting** spaces Instagram requests (roughly 3–5 seconds jitter between calls, token bucket, and an hourly budget of 200 requests). Hitting limits raises a rate-limit error; wait and retry.
- **No bulk scraping** — do not loop thousands of profiles or posts through the tools.
- **Avoid datacenter IPs** — Instagram often blocks cloud VPS IPs. Prefer a home or office network where you normally use Instagram. **`check_auth`** warns when common cloud environment variables are detected.
- Use a **secondary account** and exported cookies rather than hammering anonymous endpoints.

## Legal and terms of use

**Not affiliated with, endorsed by, or sponsored by Meta Platforms, Inc. Instagram is a trademark of Meta.**

You are responsible for complying with Instagram’s Terms of Use, applicable copyright law, and privacy rules. This project provides **read-only** access to public (or session-allowed) content for personal/agent assistance. Do not use it to harass users, bypass paywalls, or redistribute media against creators’ rights. Respect creators and platform policies.

## Demo

<!-- TODO: Record a short demo GIF (Claude Desktop or Cursor calling get_post on a public post) and save as docs/assets/demo.gif -->

![Demo: get_post in an MCP client](https://raw.githubusercontent.com/vinihuge/igsight-mcp/main/docs/assets/demo.gif)

## Docker

Published images: [`ghcr.io/vinihuge/igsight-mcp`](https://github.com/vinihuge/igsight-mcp/pkgs/container/igsight-mcp).

**Security:** the default command binds **streamable HTTP** MCP to **`0.0.0.0:8000`**, so anyone who can reach the port can use the server unless you protect it. **Strongly recommended:** set **`IGSIGHT_HTTP_TOKEN`** to a long random secret and configure MCP clients to send `Authorization: Bearer <token>`. Prefer not publishing the port on untrusted networks; use stdio mode (below) when the client runs on the same host.

The image includes **ffmpeg** and the `igsight-mcp` wheel installed with [uv](https://docs.astral.sh/uv/). It runs as a non-root user. **No local Whisper model** is baked in; use API transcription env vars (see above) or install `[local]` only in custom builds.

Mount volumes for cache and cookies so data survives restarts:

| Mount / env | Purpose |
| --- | --- |
| `-v igsight-cache:/home/igsight/.cache/igsight-mcp` | Post and media cache (`IGSIGHT_CACHE_DIR`) |
| `-v /path/to/cookies.txt:/home/igsight/cookies.txt:ro` + `-e IGSIGHT_COOKIES_FILE=/home/igsight/cookies.txt` | Netscape cookies for authenticated requests |

**HTTP (default transport)**

```bash
docker run --rm -p 8000:8000 \
  -e IGSIGHT_HTTP_TOKEN="replace-with-a-long-random-secret" \
  -v igsight-cache:/home/igsight/.cache/igsight-mcp \
  -v "$HOME/.config/igsight/cookies.txt:/home/igsight/cookies.txt:ro" \
  -e IGSIGHT_COOKIES_FILE=/home/igsight/cookies.txt \
  ghcr.io/vinihuge/igsight-mcp:latest
```

**Stdio (Claude Desktop, Cursor, Grok Bot, etc.)**

Use `-i` so the MCP client can use stdin/stdout; override the default HTTP command with `--transport stdio`:

```bash
docker run --rm -i \
  -v igsight-cache:/home/igsight/.cache/igsight-mcp \
  -v "$HOME/.config/igsight/cookies.txt:/home/igsight/cookies.txt:ro" \
  -e IGSIGHT_COOKIES_FILE=/home/igsight/cookies.txt \
  ghcr.io/vinihuge/igsight-mcp:latest \
  --transport stdio
```

Example MCP client config: `command` = `docker`, `args` = `["run", "--rm", "-i", "-v", "igsight-cache:/home/igsight/.cache/igsight-mcp", "ghcr.io/vinihuge/igsight-mcp:latest", "--transport", "stdio"]` (add cookie mounts and `env` as needed).

## Development

Requires [uv](https://docs.astral.sh/uv/). See [CONTRIBUTING.md](CONTRIBUTING.md).

```bash
uv sync --all-groups
make check          # ruff, mypy --strict, pytest
uv run igsight-mcp  # stdio MCP server
uvx --from . igsight-mcp
```

## Support the project

If igsight-mcp saves you time, consider sponsoring on [GitHub Sponsors](https://github.com/sponsors/vinihuge).

### Crypto

Always double-check the network before sending; funds sent on the wrong network may be lost.

| Network | Address | QR |
| --- | --- | --- |
| Bitcoin (BTC) | `bc1qfm4mhns9j4s589lhc9xq6asxpf5x93vhxkdlnn` | ![Bitcoin QR](https://raw.githubusercontent.com/vinihuge/igsight-mcp/main/assets/donate/btc.png) |
| EVM (Ethereum, BNB Smart Chain, Arbitrum; ETH and USDC/USDT on those networks) | `0x816895DFd46328258Bc11E133bD6d659Ccd0E323` | ![EVM QR](https://raw.githubusercontent.com/vinihuge/igsight-mcp/main/assets/donate/evm.png) |
| Solana (SOL, USDC) | `7zvKEwXR5KpbwoorQ4JhjhPSDDkwujKu7tN4BSeAq3Ci` | ![Solana QR](https://raw.githubusercontent.com/vinihuge/igsight-mcp/main/assets/donate/solana.png) |
| Tron (TRX, USDT TRC-20) | `TRk3jC7FjkDpLyHThVogP5pPeeufkSTQ7C` | ![Tron QR](https://raw.githubusercontent.com/vinihuge/igsight-mcp/main/assets/donate/tron.png) |

---

Built by Vinícius · creator of [WeTrackWise](https://wetrackwise.com)
