instagram-mcp
Enables team members to publish Instagram carousels and single images to their own professional Instagram accounts directly from Claude conversations, with per-user authentication and idempotent publishing.
README
instagram-mcp
A remote MCP server that lets each team member publish Instagram carousels and single images directly from a Claude conversation — to their own Instagram professional account, and nobody else's.
The bearer token identifies the person. The person maps to exactly one Instagram account in the database. No tool ever takes an Instagram account id as a parameter, so posting to a teammate's account by passing the wrong id is structurally impossible.
The Meta app runs in Development mode with every team member added as an Instagram Tester — No Meta App Review, no OAuth login flow, no going Live. That is deliberate.
Connect it to Claude (send this section to a teammate as-is)
You need two things from the admin: the server URL and your personal access token (starts with igmcp_). Keep the token like a password — anyone holding it can post to your Instagram account.
-
In Claude, open Settings → Connectors → Add custom connector.
-
Paste this URL:
https://YOUR-DEPLOYMENT.vercel.app/api/mcp(the admin will give you the real hostname)
-
Where the connector asks for authentication, add this header — Name on the left, value on the right:
Authorization: Bearer igmcp_your_token_hereHeader name:
Authorization. Header value: the wordBearer, one space, then your token. Nothing else. -
Save. In any conversation, you can now say things like "publish these 5 slides as a carousel with this caption" and Claude will upload the images and post them to your account.
What you can ask Claude to do:
- Publish a carousel (2–10 images, one caption for the whole post)
- Publish a single image
- Check how many posts you have left today (Instagram caps API publishing at 100 per 24h)
- Check your token health (your Instagram connection auto-renews well before it expires; this tells you if anything's wrong)
- List your recent posts (only ever yours)
If a publish fails halfway, just ask Claude to try the same publish again — the server resumes where it left off and will not double-post.
Onboarding a new team member (admin)
Prerequisites, once per person:
- Their Instagram account must be a professional account (Business or Creator).
- On developers.facebook.com open the Meta app → Instagram → API setup with Instagram Login → add their account as an Instagram Tester. They must accept the invitation (Instagram app → Settings → Website permissions → Apps and websites → Tester invites).
- Generate a long-lived access token for their account from the app dashboard (the "Generate token" button next to the tester account). Copy the token and note the account's user id.
Then seed them (from your machine, in this repo, with .env.local filled):
npm run add-member -- --name "Ada" --ig-user-id 17840000000000000 --ig-username ada.builds
# pastes the long-lived IG token when prompted (kept out of shell history)
The script verifies the token live against graph.instagram.com, refuses to seed if the token belongs to a different account than the id you passed, and prints the member's igmcp_ bearer token once. Send it to them over a secure channel along with the "Connect it to Claude" section above.
To revoke someone: set revoked_at = now() on their row in team_members. Their token starts returning 401 immediately.
Architecture
instagram-mcp/
├── api/
│ ├── mcp.ts # MCP endpoint (Streamable HTTP), bearer auth wrapper
│ └── cron/refresh-tokens.ts # Vercel Cron target (daily; refreshes tokens nearing expiry)
├── src/
│ ├── auth.ts # bearer lookup → resolves the calling member
│ ├── crypto.ts # AES-256-GCM for IG tokens, SHA-256 for bearer hashes
│ ├── instagram.ts # containers, polling, publish, refresh, idempotent resume
│ ├── storage.ts # R2 uploads (per-member key prefix)
│ ├── db.ts # Supabase (service role)
│ ├── refresh.ts # refresh loop shared by cron + CLI
│ └── tools/ # one file per tool
├── scripts/
│ ├── add-member.ts # seeds a member, generates their bearer token
│ └── refresh-tokens.ts # manual run of the refresh loop
├── supabase/migrations/ # schema (already applied via the Supabase connector)
├── .env.example # every key, documented
└── README.md
Key decisions:
- Transport:
mcp-handlerv2 (Vercel's MCP adapter) with@modelcontextprotocol/serverv2 — Streamable HTTP only; the deprecated HTTP+SSE transport was removed upstream in v2, which is exactly what we want. No hand-rolled transport. - Host: everything talks to
https://graph.instagram.com(Instagram Login path).graph.facebook.combelongs to the Facebook Login path and fails with a misleading token-parse error — most tutorials get this wrong. - Auth:
Authorization: Bearer <token>on every request. The token is hashed (SHA-256), looked up, and re-checked with a constant-time comparison; unknown and revoked tokens 401 before any processing. Instagram tokens live AES-256-GCM-encrypted in Postgres; bearer tokens are never stored raw. - Idempotency: the idempotency key (member + image URLs + caption) is written to
postsbefore any Meta call. Child container ids are persisted as they're created. A retry reuses FINISHED children, recreates only EXPBREDERRORed ones, and re-publishing the same parent container id is safe (media_publishis idempotent per container) — so a half-published carousel can never duplicate. - Token refresh: Vercel Cron runs daily; tokens last 60 days and each is refreshed once it enters a 25-day renewal window, so a failed run gets a fresh retry every 24h rather than one shot per month. One member failing never aborts the loop; permanent failures (revoked access, account-type change) mark the row and surface through
check_token_healthinstead of retrying forever.
Deploying (admin)
npm install
npm run typecheck && npm test # 19 unit tests, live tests skip without creds
vercel login
vercel link # or create the project
# Set every var from .env.example in Vercel → Project → Settings → Environment Variables
vercel --prod
Then put the deployment URL into the "Connect it to Claude" section above.
Supabase must be a dedicated project that hosts only this server — not a project shared with another app. team_members and posts are generic names and the service-role client has full table access, so sharing a schema with an unrelated product is a collision (and blast-radius) risk. Create the project under your own account, then apply the migration in supabase/migrations/ via the SQL editor or the Supabase MCP connector.
R2 bucket needs public access enabled (custom domain or r2.dev) matching R2_PUBLIC_BASE_URL.
Live acceptance tests
With .env.local filled and at least one member seeded:
LIVE_MEMBER_BEARER_TOKEN=igmcp_... npm test # upload + token health, no posting
LIVE_MEMBER_BEARER_TOKEN=igmcp_... LIVE_PUBLISH=1 npm test # ⚠ creates REAL posts
# add LIVE_MEMBER_BEARER_TOKEN_2=igmcp_... for the two-members-two-accounts test
Operational notes
- Quiet failure mode #1 is an expired token — posting stops and nobody notices. The cron marks failures loudly (non-200 → red run in the Vercel dashboard) and
check_token_healthreports days-to-expiry and refresh failures per member. - Instagram caps publishing at 100 posts per account per rolling 24h;
get_publishing_limitreads the live counter. - Containers expire after ~24h and there's a ceiling of ~50 pending containers per account — another reason the retry path reuses containers instead of minting new ones.
- Keep carousel slides the same aspect ratio; Instagram crops everything to match the first slide. JPEG/PNG only, ≤ 8 MB.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。
mcp-server-qdrant
这个仓库展示了如何为向量搜索引擎 Qdrant 创建一个 MCP (Managed Control Plane) 服务器的示例。