Skip to main content
Glama
pedroantonnio

Instagram Public MCP

README.md
# Instagram Public MCP for Vercel

A remote MCP server written in Python that queries **public Instagram data only**
without an Instagram login, cookies, passwords, or saved account sessions.

## Important: mobile-feed Instaloader patch

This build does **not** use the stock Instaloader 4.15.3 package.

It pins the anonymous profile/post fix from Instaloader pull request #2722 at:

```text
3f72b47466cc505b92c6e9b0ca2f5689e93a6a89
```

Dependency:

```text
instaloader @ https://github.com/alimony/instaloader/archive/3f72b47466cc505b92c6e9b0ca2f5689e93a6a89.zip
```

The patch changes anonymous behavior so that:

- profile resolution can fall back from `api/v1/users/web_profile_info/`
  to `api/v1/feed/user/{username}/username/`;
- anonymous post pagination uses `api/v1/feed/user/{id}/`;
- post pages use `max_id` pagination;
- items are converted through Instaloader's iPhone/mobile response model;
- failures from `web_profile_info` can reach the feed fallback immediately
  instead of waiting through a long retry/backoff loop.

No authenticated Instagram account is used.

## Architecture

```text
MCP Client
    |
    v
Vercel /api/mcp
    |
    v
Patched Instaloader (PR #2722)
    |
    v
Instagram mobile feed endpoint
```

## MCP Tools

### `get_instagram_profile`

Returns public metadata for an Instagram profile.

```json
{
  "username": "instagram"
}
```

### `get_instagram_posts`

Returns recent public posts.

```json
{
  "username": "instagram",
  "count": 3
}
```

### `debug_instagram_connection`

Inspects the raw legacy `web_profile_info` HTTP response. This tool remains
available for diagnostics, but the patched Instaloader can fall back to the
mobile feed endpoint when that endpoint is refused.

```json
{
  "username": "instagram"
}
```

## MCP Resources

```text
instagram://profile/{username}
instagram://profile/{username}/posts
```

## Cache

Default in-memory cache:

```text
CACHE_TTL_SECONDS=600
DEFAULT_POST_COUNT=12
MAX_POST_COUNT=30
```

Set `CACHE_TTL_SECONDS=0` to disable it.

Vercel instances are ephemeral, so this cache is per warm function instance,
not a globally shared cache.

## Deploy to Vercel

```bash
npm install -g vercel
vercel --prod
```

The included `vercel.json` deploys the function to São Paulo:

```json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "regions": ["gru1"]
}
```

MCP endpoint:

```text
https://YOUR-PROJECT.vercel.app/api/mcp
```

Health endpoint:

```text
https://YOUR-PROJECT.vercel.app/api/health
```

## Local development

```bash
python -m venv .venv
pip install -r requirements.txt
uvicorn api.index:app --reload
```

MCP endpoint:

```text
http://127.0.0.1:8000/api/mcp
```

## Cursor

`.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "instagram-public": {
      "url": "https://YOUR-PROJECT.vercel.app/api/mcp"
    }
  }
}
```

## Security

This repository contains no Instagram account credentials.

It does not contain or require:

- Instagram username/password credentials
- `sessionid`
- `csrftoken`
- `fb_dtsg`
- authenticated account IDs
- saved Instaloader sessions
- Instagram cookies

## Limitations

The server only queries public data and does not attempt to bypass private
profiles.

Instagram may still rate-limit or block anonymous traffic based on the
deployment IP. The mobile-feed patch fixes the known broken anonymous
`web_profile_info`/timeline path, but it cannot guarantee that Instagram will
accept traffic from every hosting provider or IP range.


## v2.1.1 profile compatibility fix

The anonymous mobile-feed fallback may omit optional profile fields that are
normally present in `web_profile_info`.

Version 2.1.1 reads profile properties defensively. Missing values such as
`biography`, `external_url`, or business-account metadata are returned as
`null` instead of causing `get_instagram_profile` to fail.

The post-fetching path is unchanged from v2.1.0.