Instagram MCP Server

Instagram MCP Server

A production-ready Remote MCP Server that gives Claude direct, tool-based access to your Instagram Business account through the Meta Graph API — profile data, posts, comments, publishing, insights, analytics, hashtags, messaging, and real-time webhooks.

Category
访问服务器

README

📸 Instagram MCP Server

A production-ready Remote MCP (Model Context Protocol) Server that gives Claude direct, tool-based access to your Instagram Business account through the Meta Graph API — profile data, posts, comments, publishing, insights, analytics, hashtags, messaging, and real-time webhooks.

Built with TypeScript, Node.js, Express, and the official @modelcontextprotocol/sdk.


Table of Contents


What this is (and isn't)

This project is a real, working integration between Claude and the Instagram Graph API for Professional (Business/Creator) accounts. It is not a wrapper around the consumer Instagram app, and it cannot do anything the Graph API itself doesn't support. Where Meta's API has a real limitation (no follower-list endpoint, no general story-history endpoint, no competitor-audience data), this server surfaces a clear error explaining the limitation instead of fabricating data — see Known API Limitations.

You need:

  • An Instagram Professional account (Business or Creator)
  • Linked to a Facebook Page
  • A Meta Developer App with the Instagram Graph API product added

Features / Tool Reference

Every feature is exposed as an MCP tool Claude can call directly.

Category Tools
Profile getProfile, getUsername, getBiography, getFollowers, getFollowing, getProfilePicture, getMediaCount
Media getRecentPosts, getReels, getStories*, getMediaMetadata, getMediaUrl, getCaption, getTaggedUsers, getLocation
Comments getComments, replyComment, deleteComment, hideComment
Publishing publishPost, publishCarouselPost, publishReel, createMediaContainer, schedulePost, getPublishingStatus
Insights getFollowerGrowth, getReach, getImpressions, getProfileVisits, getWebsiteClicks, getEngagement, getAccountsReached, getAccountsEngaged, getMediaInsights
Analytics getTopPerformingPosts, getTopPerformingReels, getAverageEngagement, getBestPostingTime, weeklyAnalytics, monthlyAnalytics, comparePosts, compareReels, generateAnalyticsSummary
Messaging getMessages, getConversationHistory, sendMessage, replyMessage
Hashtags searchHashtag, getHashtags
Business getAccountInformation, businessDiscovery, competitorAnalysis*
Webhooks getRecentMentions, getRecentCommentEvents

* getStories and competitorAnalysis intentionally return an explanatory error — see Known API Limitations.

54 tools total. Run the server and call tools/list over MCP, or see examples/api-requests.md, for the live list.


Architecture

instagram-mcp/
├── src/
│   ├── index.ts               # process bootstrap (listen, graceful shutdown)
│   ├── server.ts               # Express app assembly (middleware + routes)
│   ├── config/                 # env validation (Zod) + constants
│   ├── routes/                 # /mcp, /auth, /webhooks, /health
│   ├── controllers/             # OAuth setup controller
│   ├── services/
│   │   ├── graph/               # low-level Graph API HTTP client (auth, retries, error mapping)
│   │   └── instagram/           # profile, media, comments, publishing, insights, analytics, hashtags, messaging, business discovery
│   ├── mcp/
│   │   ├── mcpServer.ts         # McpServer factory — registers every tool
│   │   └── tools/                # one file per tool category (Zod schemas + handlers)
│   ├── middlewares/              # auth, rate limiting, validation, error handling, logging
│   ├── utils/                    # logger, errors, cache, retry, crypto
│   ├── types/                    # shared TypeScript types
│   ├── auth/                      # OAuth token exchange logic
│   ├── storage/                   # encrypted-at-rest token store
│   └── webhooks/                  # signature verification + event router
├── tests/
│   ├── unit/                      # crypto, retry, cache, service-level (mocked via nock)
│   └── integration/                # full Express app via supertest
├── examples/                       # sample MCP config + curl requests
├── Dockerfile / docker-compose.yml
├── render.yaml / railway.json / fly.toml
└── .github/workflows/ci.yml

Design choices worth knowing about:

  • The Remote MCP endpoint (POST /mcp) uses the SDK's stateless Streamable HTTP transport — a fresh McpServer + transport pair per request. This makes the server trivially horizontally scalable. It does not support server-initiated push over a long-lived connection; use the polling-style getRecentMentions / getRecentCommentEvents tools (fed by the webhook listener) instead.
  • Tokens are encrypted at rest with AES-256-GCM using a key derived from TOKEN_ENCRYPTION_KEY.
  • All Graph API calls go through a single GraphClient that adds appsecret_proof, retries transient/rate-limited failures with backoff, and normalizes Meta's error shapes into typed AppError subclasses.
  • Analytics like "best posting time" and "compare posts" are computed locally from real data pulled via Graph API primitives — Meta does not expose these as first-class endpoints.

Quick Start

git clone <this-repo-url> instagram-mcp
cd instagram-mcp
npm install
cp .env.example .env
# edit .env with your Meta App credentials (see below)
npm run dev

Server starts on http://localhost:3000. Health check: curl http://localhost:3000/health.


Meta App Setup

1. Create a Meta App

  1. Go to https://developers.facebook.com/apps → Create App.
  2. Choose type Business.
  3. In the App Dashboard, add the Instagram Graph API product (search "Instagram" in "Add Product").
  4. Note your App ID and App Secret (Settings → Basic) — these go in META_APP_ID / META_APP_SECRET.

2. Link a Facebook Page + Instagram Business Account

The Instagram Graph API only works through a Facebook Page connection:

  1. Convert your Instagram account to a Professional Account (Business or Creator) in the Instagram app: Settings → Account type.
  2. Create or use an existing Facebook Page.
  3. Link them: Instagram app → Settings → Account → Linked accounts → Facebook, or Facebook Page → Settings → Instagram → Connect Account.
  4. Note the Facebook Page ID (Page → About → Page ID), used as FACEBOOK_PAGE_ID.

3. Generate an Access Token

Option A — Graph API Explorer (fastest for personal use):

  1. Go to https://developers.facebook.com/tools/explorer/.

  2. Select your app, select your Page, and add the permissions listed below.

  3. Generate a User Access Token, then exchange it for a long-lived token (~60 days) using:

    curl -G "https://graph.facebook.com/v21.0/oauth/access_token" \
      -d "grant_type=fb_exchange_token" \
      -d "client_id=$META_APP_ID" \
      -d "client_secret=$META_APP_SECRET" \
      -d "fb_exchange_token=$SHORT_LIVED_TOKEN"
    
  4. Put the resulting token in IG_LONG_LIVED_ACCESS_TOKEN.

  5. Find your Instagram Business Account ID:

    curl -G "https://graph.facebook.com/v21.0/$FACEBOOK_PAGE_ID" \
      -d "fields=instagram_business_account" \
      -d "access_token=$IG_LONG_LIVED_ACCESS_TOKEN"
    

    Put the returned id in IG_BUSINESS_ACCOUNT_ID.

This is the simplest path for a single-account, self-hosted deployment — set those three env vars and skip the /auth/* OAuth endpoints entirely.

Option B — Full OAuth flow (multi-user / production apps):

  1. Set META_REDIRECT_URI to https://your-domain.com/auth/callback and add it as a Valid OAuth Redirect URI in the Meta App Dashboard (Facebook Login product → Settings).
  2. GET /auth/authorize returns a URL — open it in a browser, approve the permissions.
  3. Meta redirects to /auth/callback, which exchanges the code for a long-lived token and stores it encrypted automatically.
  4. GET /auth/status confirms the connection.

4. Permissions & App Review

Required scopes (already requested by buildAuthorizationUrl):

instagram_basic
instagram_manage_insights
instagram_manage_comments
instagram_content_publish
instagram_manage_messages
pages_show_list
pages_read_engagement
pages_manage_metadata
business_management

For personal/self-use on your own account, most of these work in Development Mode with your own account added as a Test User — no App Review needed. To let other Instagram accounts authorize your app, Meta requires App Review for instagram_manage_comments, instagram_content_publish, instagram_manage_messages, and instagram_manage_insights.


Configuration

See .env.example for the full, documented list. Key variables:

Variable Required Description
META_APP_ID / META_APP_SECRET ✅ From your Meta App dashboard
TOKEN_ENCRYPTION_KEY ✅ ≥32 chars, encrypts tokens at rest
IG_LONG_LIVED_ACCESS_TOKEN / IG_BUSINESS_ACCOUNT_ID Option A Skip OAuth entirely
META_REDIRECT_URI Option B Needed only for the /auth/* OAuth flow
MCP_AUTH_TOKEN Recommended Bearer token required to call /mcp
META_WEBHOOK_VERIFY_TOKEN Optional Needed for real-time webhooks

The server refuses to start if required variables are missing or malformed (validated with Zod on boot) — check the console output for the exact field that failed.


Running Locally

npm install
npm run dev          # tsx watch mode
# or
npm run build && npm start   # production build

Other scripts: npm run lint, npm run format, npm run typecheck, npm test, npm run test:coverage.


Deployment

Docker

docker build -t instagram-mcp-server .
docker run -p 3000:3000 --env-file .env -v $(pwd)/data:/app/data instagram-mcp-server

Or with Compose:

docker compose up -d --build

Render

  1. Push this repo to GitHub.
  2. In Render: New → Blueprint, point at your repo — render.yaml is auto-detected.
  3. Fill in the secret env vars flagged sync: false in the Render dashboard.
  4. Deploy. Your Remote MCP URL will be https://<your-service>.onrender.com/mcp.

Railway

railway init
railway up

railway.json configures the Dockerfile build and health check automatically. Set env vars via railway variables set KEY=value or the dashboard.

Fly.io

fly launch --no-deploy   # detects fly.toml
fly secrets set META_APP_ID=... META_APP_SECRET=... TOKEN_ENCRYPTION_KEY=... MCP_AUTH_TOKEN=...
fly deploy

Self-host (bare metal / VM)

npm ci --omit=dev
npm run build
NODE_ENV=production node dist/index.js

Put it behind a reverse proxy (nginx/Caddy) for TLS termination — Claude's Remote MCP requires HTTPS in production.


Connecting Claude

Once deployed with a public HTTPS URL:

  1. In claude.ai: Settings → Connectors → Add custom connector.
  2. Enter your MCP URL: https://your-domain.com/mcp.
  3. If you set MCP_AUTH_TOKEN, add it as a Bearer token / custom header (Authorization: Bearer <token>) in the connector's auth settings.
  4. Claude will call initialize and tools/list automatically and the Instagram tools become available in your conversation.

For Claude Desktop or other MCP clients that read a JSON config file, see examples/claude-mcp-config.json.

See examples/api-requests.md for raw curl-based examples of the MCP JSON-RPC protocol if you want to test independent of Claude.


Webhooks (real-time updates)

To receive comments/mentions in near-real-time instead of polling:

  1. Set META_WEBHOOK_VERIFY_TOKEN to a random string.
  2. In the Meta App Dashboard → Webhooks → Instagram, subscribe to comments, mentions (and others as needed) with callback URL https://your-domain.com/webhooks and the same verify token.
  3. Meta will GET /webhooks once to verify (handled automatically), then POST /webhooks on every event.
  4. Call the getRecentMentions / getRecentCommentEvents MCP tools to read the most recent events received (kept in an in-memory ring buffer — swap for persistent storage if you need durability across restarts).

Testing

npm test                 # everything
npm run test:unit        # unit tests (crypto, retry, cache, services via nock mocks)
npm run test:integration # full Express app via supertest, including a live MCP handshake
npm run test:coverage

27 tests ship with the project, covering encryption round-trips, retry/backoff logic, caching, comment/publishing service behavior against a mocked Graph API, and an end-to-end MCP initialize handshake against the real app.


Security Notes

  • Tokens are never logged (redacted in the pino logger config) and are encrypted at rest with AES-256-GCM.
  • .env is git-ignored; only .env.example (no real secrets) is committed.
  • appsecret_proof is sent on every Graph API call by default (META_APP_SECRET_PROOF=true) to prevent token replay if a token leaks.
  • Webhook payloads are (optionally) signature-verified against X-Hub-Signature-256 using your App Secret — wire verifySignature into webhookRoutes.ts if you want to reject unsigned/forged payloads outright (currently logged; enable strict rejection for production hardening).
  • Set MCP_AUTH_TOKEN in any environment reachable from the public internet.

Known API Limitations

The Instagram Graph API does not support everything a full "clone" of the Instagram app would need. This server is honest about it:

Requested feature Reality
List of follower/following usernames Not exposed — only aggregate counts, for user privacy.
Reading Stories Only stories this app itself published are readable, and only within 24h. No general story-history endpoint exists.
Competitor analysis (ads, demographics, audience overlap) Business Discovery exposes only public profile/media stats of other accounts — nothing beyond what's visible on their public profile.
Native "schedule for later" No such flag exists on the Graph API; this server creates the container immediately and defers the media_publish call with an in-process timer (persist this in a real queue for production-grade durability across restarts).
DM automation outside the 24h window Meta restricts free-form messaging to a 24-hour window after the user last messaged you, or requires approved message tags — this is a platform policy, not a limitation of this code.

Troubleshooting

"Environment validation failed" on startup Check the console output — it lists exactly which env var is missing/invalid.

AuthenticationError: Instagram access token is invalid or expired Long-lived tokens last ~60 days. Call POST /auth/refresh, or re-run the Graph API Explorer token exchange and update IG_LONG_LIVED_ACCESS_TOKEN.

GraphApiError with code 100 on publishing Usually means the media URL isn't publicly reachable/valid, or the account lacks instagram_content_publish permission.

Rate limit errors (RateLimitError) The client retries automatically with backoff; if it persists, you're hitting Meta's per-app/per-user call limits — space out requests or wait.

Claude can't connect to /mcp Confirm the URL is HTTPS and publicly reachable, and that any MCP_AUTH_TOKEN you configured matches exactly what's set in Claude's connector settings.


FAQ

Do I need App Review to use this on my own account? No — Development Mode + adding your own account as a Test User is enough for personal use of all read/write tools.

Can this manage multiple Instagram accounts? The current token store holds one account's credentials. For multi-account support, extend TokenStore to key by account ID and add an accountId parameter to the relevant tools.

Does this work with Creator accounts, not just Business? Yes — the Graph API treats Business and Creator accounts the same way for these endpoints.

Is there a database? No — token storage is a single encrypted JSON file by default, so the project runs anywhere without provisioning infrastructure. Swap src/storage/tokenStore.ts for a Redis/Postgres-backed implementation if you need multi-instance deployments.


License

MIT — see LICENSE.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选