@exileum/meta-mcp 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +335 -0
  3. package/dist/config.d.ts +10 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +11 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/index.d.ts +4 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +93 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/prompts/index.d.ts +3 -0
  12. package/dist/prompts/index.d.ts.map +1 -0
  13. package/dist/prompts/index.js +61 -0
  14. package/dist/prompts/index.js.map +1 -0
  15. package/dist/resources/instagram.d.ts +4 -0
  16. package/dist/resources/instagram.d.ts.map +1 -0
  17. package/dist/resources/instagram.js +17 -0
  18. package/dist/resources/instagram.js.map +1 -0
  19. package/dist/resources/threads.d.ts +4 -0
  20. package/dist/resources/threads.d.ts.map +1 -0
  21. package/dist/resources/threads.js +17 -0
  22. package/dist/resources/threads.js.map +1 -0
  23. package/dist/services/meta-client.d.ts +25 -0
  24. package/dist/services/meta-client.d.ts.map +1 -0
  25. package/dist/services/meta-client.js +115 -0
  26. package/dist/services/meta-client.js.map +1 -0
  27. package/dist/tools/instagram/comments.d.ts +4 -0
  28. package/dist/tools/instagram/comments.d.ts.map +1 -0
  29. package/dist/tools/instagram/comments.js +111 -0
  30. package/dist/tools/instagram/comments.js.map +1 -0
  31. package/dist/tools/instagram/hashtags.d.ts +4 -0
  32. package/dist/tools/instagram/hashtags.d.ts.map +1 -0
  33. package/dist/tools/instagram/hashtags.js +77 -0
  34. package/dist/tools/instagram/hashtags.js.map +1 -0
  35. package/dist/tools/instagram/media.d.ts +4 -0
  36. package/dist/tools/instagram/media.d.ts.map +1 -0
  37. package/dist/tools/instagram/media.js +82 -0
  38. package/dist/tools/instagram/media.js.map +1 -0
  39. package/dist/tools/instagram/mentions.d.ts +4 -0
  40. package/dist/tools/instagram/mentions.d.ts.map +1 -0
  41. package/dist/tools/instagram/mentions.js +41 -0
  42. package/dist/tools/instagram/mentions.js.map +1 -0
  43. package/dist/tools/instagram/messaging.d.ts +4 -0
  44. package/dist/tools/instagram/messaging.d.ts.map +1 -0
  45. package/dist/tools/instagram/messaging.js +80 -0
  46. package/dist/tools/instagram/messaging.js.map +1 -0
  47. package/dist/tools/instagram/profile.d.ts +4 -0
  48. package/dist/tools/instagram/profile.d.ts.map +1 -0
  49. package/dist/tools/instagram/profile.js +86 -0
  50. package/dist/tools/instagram/profile.js.map +1 -0
  51. package/dist/tools/instagram/publishing.d.ts +4 -0
  52. package/dist/tools/instagram/publishing.d.ts.map +1 -0
  53. package/dist/tools/instagram/publishing.js +202 -0
  54. package/dist/tools/instagram/publishing.js.map +1 -0
  55. package/dist/tools/meta/auth.d.ts +4 -0
  56. package/dist/tools/meta/auth.d.ts.map +1 -0
  57. package/dist/tools/meta/auth.js +82 -0
  58. package/dist/tools/meta/auth.js.map +1 -0
  59. package/dist/tools/threads/insights.d.ts +4 -0
  60. package/dist/tools/threads/insights.d.ts.map +1 -0
  61. package/dist/tools/threads/insights.js +37 -0
  62. package/dist/tools/threads/insights.js.map +1 -0
  63. package/dist/tools/threads/media.d.ts +4 -0
  64. package/dist/tools/threads/media.d.ts.map +1 -0
  65. package/dist/tools/threads/media.js +84 -0
  66. package/dist/tools/threads/media.js.map +1 -0
  67. package/dist/tools/threads/profile.d.ts +4 -0
  68. package/dist/tools/threads/profile.d.ts.map +1 -0
  69. package/dist/tools/threads/profile.js +42 -0
  70. package/dist/tools/threads/profile.js.map +1 -0
  71. package/dist/tools/threads/publishing.d.ts +4 -0
  72. package/dist/tools/threads/publishing.d.ts.map +1 -0
  73. package/dist/tools/threads/publishing.js +223 -0
  74. package/dist/tools/threads/publishing.js.map +1 -0
  75. package/dist/tools/threads/replies.d.ts +4 -0
  76. package/dist/tools/threads/replies.d.ts.map +1 -0
  77. package/dist/tools/threads/replies.js +99 -0
  78. package/dist/tools/threads/replies.js.map +1 -0
  79. package/dist/types.d.ts +45 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +2 -0
  82. package/dist/types.js.map +1 -0
  83. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yury Pikhtarev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,335 @@
1
+ # meta-mcp
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@exileum/meta-mcp)](https://www.npmjs.com/package/@exileum/meta-mcp)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ MCP server for **Instagram Graph API** (v25.0), **Threads API**, and **Meta platform** management. Publish content, manage comments, view insights, and handle DMs — all through AI assistants.
7
+
8
+ ## Quick Start
9
+
10
+ Add to your MCP client config:
11
+
12
+ ```json
13
+ {
14
+ "mcpServers": {
15
+ "meta": {
16
+ "command": "npx",
17
+ "args": ["-y", "@exileum/meta-mcp"],
18
+ "env": {
19
+ "INSTAGRAM_ACCESS_TOKEN": "your_ig_token",
20
+ "INSTAGRAM_USER_ID": "your_ig_user_id",
21
+ "THREADS_ACCESS_TOKEN": "your_threads_token",
22
+ "THREADS_USER_ID": "your_threads_user_id"
23
+ }
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ Only set the variables for the platforms you use.
30
+
31
+ ### Manual Installation
32
+
33
+ ```bash
34
+ git clone https://github.com/exileum/meta-mcp.git
35
+ cd meta-mcp
36
+ npm install
37
+ npm run build
38
+ ```
39
+
40
+ ```json
41
+ {
42
+ "mcpServers": {
43
+ "meta": {
44
+ "command": "node",
45
+ "args": ["/path/to/meta-mcp/dist/index.js"],
46
+ "env": {
47
+ "INSTAGRAM_ACCESS_TOKEN": "your_ig_token",
48
+ "INSTAGRAM_USER_ID": "your_ig_user_id",
49
+ "THREADS_ACCESS_TOKEN": "your_threads_token",
50
+ "THREADS_USER_ID": "your_threads_user_id"
51
+ }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ## Environment Variables
58
+
59
+ | Variable | Required | Description |
60
+ |----------|----------|-------------|
61
+ | `INSTAGRAM_ACCESS_TOKEN` | For Instagram | Instagram Graph API access token |
62
+ | `INSTAGRAM_USER_ID` | For Instagram | Instagram Business/Creator account ID |
63
+ | `THREADS_ACCESS_TOKEN` | For Threads | Threads API access token |
64
+ | `THREADS_USER_ID` | For Threads | Threads user ID |
65
+ | `META_APP_ID` | For token/webhook tools | Meta App ID |
66
+ | `META_APP_SECRET` | For token/webhook tools | Meta App Secret |
67
+
68
+ ## Account Requirements
69
+
70
+ | Platform | Account Type | Notes |
71
+ |----------|-------------|-------|
72
+ | **Instagram** | Business or Creator | Personal accounts cannot use the Graph API. Free to switch in settings |
73
+ | **Threads** | Any account | Instagram link no longer required since Sep 2025 |
74
+ | **Meta** (token/webhook) | Meta Developer App | Create at [developers.facebook.com](https://developers.facebook.com) |
75
+
76
+ ## Features
77
+
78
+ - **57 tools** across Instagram (33), Threads (18), and Meta platform (6)
79
+ - **Instagram**: Publish photos/videos/reels/stories/carousels with alt text, manage comments, view insights, search hashtags, handle DMs, manage collaboration invites
80
+ - **Threads**: Publish text/images/videos/carousels with polls, GIFs, topic tags, link attachments, alt text, spoiler flags; manage replies; search posts; delete posts; view insights
81
+ - **Meta**: Token exchange/refresh/debug, webhook management
82
+ - **2 resources**: Instagram profile, Threads profile
83
+ - **2 prompts**: Cross-platform content publishing, analytics report
84
+ - Rate limit tracking via `x-app-usage` header
85
+
86
+ ## Tools
87
+
88
+ ### Meta Platform (6)
89
+
90
+ | Tool | Description |
91
+ |------|-------------|
92
+ | `meta_exchange_token` | Exchange short-lived token for long-lived token (~60 days) |
93
+ | `meta_refresh_token` | Refresh a long-lived token before expiration |
94
+ | `meta_debug_token` | Inspect token validity, expiration, and scopes |
95
+ | `meta_get_app_info` | Get Meta App information |
96
+ | `meta_subscribe_webhook` | Subscribe to webhook notifications |
97
+ | `meta_get_webhook_subscriptions` | List current webhook subscriptions |
98
+
99
+ ### Instagram — Publishing (6)
100
+
101
+ | Tool | Description |
102
+ |------|-------------|
103
+ | `ig_publish_photo` | Publish a photo post (supports alt_text) |
104
+ | `ig_publish_video` | Publish a video post |
105
+ | `ig_publish_carousel` | Publish a carousel/album (2-10 items, supports alt_text per item) |
106
+ | `ig_publish_reel` | Publish a Reel (supports alt_text) |
107
+ | `ig_publish_story` | Publish a Story (24hr) |
108
+ | `ig_get_container_status` | Check media container processing status |
109
+
110
+ ### Instagram — Media (5)
111
+
112
+ | Tool | Description |
113
+ |------|-------------|
114
+ | `ig_get_media_list` | List published media |
115
+ | `ig_get_media` | Get media details |
116
+ | `ig_delete_media` | Delete a media post |
117
+ | `ig_get_media_insights` | Get media analytics (views, reach, saved, shares) |
118
+ | `ig_toggle_comments` | Enable/disable comments on a post |
119
+
120
+ ### Instagram — Comments (7)
121
+
122
+ | Tool | Description |
123
+ |------|-------------|
124
+ | `ig_get_comments` | Get comments on a post |
125
+ | `ig_get_comment` | Get comment details |
126
+ | `ig_post_comment` | Post a comment |
127
+ | `ig_get_replies` | Get replies to a comment |
128
+ | `ig_reply_to_comment` | Reply to a comment |
129
+ | `ig_hide_comment` | Hide/unhide a comment |
130
+ | `ig_delete_comment` | Delete a comment |
131
+
132
+ ### Instagram — Profile & Insights (5)
133
+
134
+ | Tool | Description |
135
+ |------|-------------|
136
+ | `ig_get_profile` | Get account profile info |
137
+ | `ig_get_account_insights` | Get account-level analytics (views, reach, follower_count) |
138
+ | `ig_business_discovery` | Look up another business account |
139
+ | `ig_get_collaboration_invites` | Get pending collaboration invites |
140
+ | `ig_respond_collaboration_invite` | Accept or decline collaboration invites |
141
+
142
+ ### Instagram — Hashtags (4)
143
+
144
+ | Tool | Description |
145
+ |------|-------------|
146
+ | `ig_search_hashtag` | Search hashtag by name |
147
+ | `ig_get_hashtag` | Get hashtag info |
148
+ | `ig_get_hashtag_recent` | Get recent media for a hashtag |
149
+ | `ig_get_hashtag_top` | Get top media for a hashtag |
150
+
151
+ ### Instagram — Mentions & Tags (2)
152
+
153
+ | Tool | Description |
154
+ |------|-------------|
155
+ | `ig_get_mentioned_comments` | Get comments mentioning you |
156
+ | `ig_get_tagged_media` | Get media you're tagged in |
157
+
158
+ ### Instagram — Messaging (4)
159
+
160
+ | Tool | Description |
161
+ |------|-------------|
162
+ | `ig_get_conversations` | List DM conversations |
163
+ | `ig_get_messages` | Get messages in a conversation |
164
+ | `ig_send_message` | Send a DM |
165
+ | `ig_get_message` | Get message details |
166
+
167
+ ### Threads — Publishing (7)
168
+
169
+ | Tool | Description |
170
+ |------|-------------|
171
+ | `threads_publish_text` | Publish a text post (supports polls, GIFs, link attachments, topic tags, quote posts, spoiler flag) |
172
+ | `threads_publish_image` | Publish an image post (supports alt_text, topic tags, spoiler flag) |
173
+ | `threads_publish_video` | Publish a video post (supports alt_text, topic tags, spoiler flag) |
174
+ | `threads_publish_carousel` | Publish a carousel (2-20 items, supports alt_text per item) |
175
+ | `threads_delete_post` | Delete a post (max 100/day) |
176
+ | `threads_get_container_status` | Check container processing status |
177
+ | `threads_get_publishing_limit` | Check remaining publishing quota (250 posts/day) |
178
+
179
+ ### Threads — Media & Search (3)
180
+
181
+ | Tool | Description |
182
+ |------|-------------|
183
+ | `threads_get_posts` | List published posts (includes topic_tag, poll, GIF fields) |
184
+ | `threads_get_post` | Get post details |
185
+ | `threads_search_posts` | Search public posts by keyword or topic tag |
186
+
187
+ ### Threads — Replies (4)
188
+
189
+ | Tool | Description |
190
+ |------|-------------|
191
+ | `threads_get_replies` | Get replies to a post |
192
+ | `threads_reply` | Reply to a post (supports image/video attachments) |
193
+ | `threads_hide_reply` | Hide a reply |
194
+ | `threads_unhide_reply` | Unhide a reply |
195
+
196
+ ### Threads — Profile (2)
197
+
198
+ | Tool | Description |
199
+ |------|-------------|
200
+ | `threads_get_profile` | Get Threads profile info (includes is_verified) |
201
+ | `threads_get_user_threads` | List user's threads |
202
+
203
+ ### Threads — Insights (2)
204
+
205
+ | Tool | Description |
206
+ |------|-------------|
207
+ | `threads_get_post_insights` | Get post analytics (views, likes, replies, reposts, quotes, clicks) |
208
+ | `threads_get_user_insights` | Get account-level analytics |
209
+
210
+ ## Resources
211
+
212
+ | Resource URI | Description |
213
+ |-------------|-------------|
214
+ | `instagram://profile` | Instagram account profile data |
215
+ | `threads://profile` | Threads account profile data (includes is_verified) |
216
+
217
+ ## Prompts
218
+
219
+ | Prompt | Description |
220
+ |--------|-------------|
221
+ | `content_publish` | Cross-post content to Instagram and Threads |
222
+ | `analytics_report` | Generate combined analytics report |
223
+
224
+ ## Setup Guide
225
+
226
+ ### Step 1: Create a Meta Developer App
227
+
228
+ 1. Go to [developers.facebook.com](https://developers.facebook.com) and log in
229
+ 2. Click **"My Apps"** -> **"Create App"**
230
+ 3. Select **"Other"** -> **"Business"** (or "None" for personal use)
231
+ 4. Enter an app name and create
232
+
233
+ Your **`META_APP_ID`** and **`META_APP_SECRET`** are in **App Settings -> Basic**.
234
+
235
+ ### Step 2: Instagram Setup
236
+
237
+ > Requires an **Instagram Business or Creator account**. Switch for free in Instagram app -> Settings -> Account type.
238
+
239
+ 1. In your Meta App, go to **"Add Products"** -> add **"Instagram Graph API"**
240
+ 2. Go to **"Instagram Graph API" -> "Settings"** and connect your Instagram Business account via a Facebook Page
241
+ 3. Open the [Graph API Explorer](https://developers.facebook.com/tools/explorer/)
242
+ - Select your app
243
+ - Add permissions: `instagram_basic`, `instagram_content_publish`, `instagram_manage_comments`, `instagram_manage_insights`, `instagram_manage_contents`, `pages_show_list`, `pages_read_engagement`
244
+ - Click **"Generate Access Token"** and authorize
245
+ 4. The generated token is short-lived (~1 hour). Exchange it for a long-lived token (~60 days):
246
+ ```
247
+ GET https://graph.facebook.com/v25.0/oauth/access_token
248
+ ?grant_type=fb_exchange_token
249
+ &client_id=YOUR_APP_ID
250
+ &client_secret=YOUR_APP_SECRET
251
+ &fb_exchange_token=SHORT_LIVED_TOKEN
252
+ ```
253
+ Or use the `meta_exchange_token` tool after setup.
254
+ 5. **Get your Instagram User ID**:
255
+ ```http
256
+ GET https://graph.facebook.com/v25.0/me/accounts?access_token=YOUR_TOKEN
257
+ ```
258
+ For each page, get the linked Instagram account:
259
+ ```http
260
+ GET https://graph.facebook.com/v25.0/{page-id}?fields=instagram_business_account&access_token=YOUR_TOKEN
261
+ ```
262
+ The `instagram_business_account.id` is your **`INSTAGRAM_USER_ID`**.
263
+
264
+ ### Step 3: Threads Setup
265
+
266
+ > Works with **any Threads account**. Instagram link no longer required since Sep 2025.
267
+
268
+ 1. In your Meta App, go to **"Add Products"** -> add **"Threads API"**
269
+ 2. Go to **"Threads API" -> "Settings"**:
270
+ - Add your Threads account as a **Threads Tester** under "Roles"
271
+ - Accept the invitation in the Threads app: **Settings -> Account -> Website permissions -> Invites**
272
+ 3. Generate an authorization URL:
273
+ ```
274
+ https://threads.net/oauth/authorize
275
+ ?client_id=YOUR_APP_ID
276
+ &redirect_uri=YOUR_REDIRECT_URI
277
+ &scope=threads_basic,threads_content_publish,threads_manage_insights,threads_manage_replies,threads_read_replies
278
+ &response_type=code
279
+ ```
280
+ For local testing, use `https://localhost/` as redirect URI (configure in App Settings -> Threads API -> Redirect URIs).
281
+ 4. After authorization, exchange the code for an access token:
282
+ ```
283
+ POST https://graph.threads.net/oauth/access_token
284
+ Content-Type: application/x-www-form-urlencoded
285
+
286
+ client_id=YOUR_APP_ID
287
+ &client_secret=YOUR_APP_SECRET
288
+ &grant_type=authorization_code
289
+ &redirect_uri=YOUR_REDIRECT_URI
290
+ &code=AUTHORIZATION_CODE
291
+ ```
292
+ 5. Exchange for a long-lived token (~60 days):
293
+ ```
294
+ GET https://graph.threads.net/access_token
295
+ ?grant_type=th_exchange_token
296
+ &client_secret=YOUR_APP_SECRET
297
+ &access_token=SHORT_LIVED_TOKEN
298
+ ```
299
+ 6. **Get your Threads User ID**:
300
+ ```http
301
+ GET https://graph.threads.net/v1.0/me?fields=id,username&access_token=YOUR_TOKEN
302
+ ```
303
+ The `id` field is your **`THREADS_USER_ID`**.
304
+
305
+ ### Token Renewal
306
+
307
+ Access tokens expire after ~60 days. Refresh before expiration:
308
+
309
+ - **Instagram**: Use `meta_exchange_token` with the current valid token
310
+ - **Threads**: Use `meta_refresh_token` or call:
311
+ ```
312
+ GET https://graph.threads.net/refresh_access_token
313
+ ?grant_type=th_refresh_token
314
+ &access_token=CURRENT_LONG_LIVED_TOKEN
315
+ ```
316
+
317
+ Check token status anytime with `meta_debug_token`.
318
+
319
+ ## Deprecated Metrics (Graph API v22.0+)
320
+
321
+ | Deprecated Metric | Replacement |
322
+ |-------------------|-------------|
323
+ | `impressions` | `views` |
324
+ | `video_views` | `views` |
325
+ | `plays` | `views` |
326
+ | `clips_replays_count` | `views` |
327
+ | `engagement` | `saves` + `shares` + `likes` + `comments` |
328
+
329
+ ## License
330
+
331
+ [MIT](LICENSE)
332
+
333
+ ---
334
+
335
+ See [CHANGELOG.md](CHANGELOG.md) for release history.
@@ -0,0 +1,10 @@
1
+ export interface MetaConfig {
2
+ appId: string;
3
+ appSecret: string;
4
+ instagramAccessToken: string;
5
+ instagramUserId: string;
6
+ threadsAccessToken: string;
7
+ threadsUserId: string;
8
+ }
9
+ export declare function loadConfig(): MetaConfig;
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,UAAU,IAAI,UAAU,CASvC"}
package/dist/config.js ADDED
@@ -0,0 +1,11 @@
1
+ export function loadConfig() {
2
+ return {
3
+ appId: process.env.META_APP_ID || "",
4
+ appSecret: process.env.META_APP_SECRET || "",
5
+ instagramAccessToken: process.env.INSTAGRAM_ACCESS_TOKEN || "",
6
+ instagramUserId: process.env.INSTAGRAM_USER_ID || "",
7
+ threadsAccessToken: process.env.THREADS_ACCESS_TOKEN || "",
8
+ threadsUserId: process.env.THREADS_USER_ID || "",
9
+ };
10
+ }
11
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,UAAU;IACxB,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE;QACpC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE;QAC5C,oBAAoB,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE;QAC9D,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE;QACpD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE;QAC1D,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE;KACjD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ export declare function createSandboxServer(): McpServer;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAyEpE,wBAAgB,mBAAmB,cAkClC"}
package/dist/index.js ADDED
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { loadConfig } from "./config.js";
5
+ import { MetaClient } from "./services/meta-client.js";
6
+ // Meta platform tools
7
+ import { registerMetaAuthTools } from "./tools/meta/auth.js";
8
+ // Instagram tools
9
+ import { registerIgPublishingTools } from "./tools/instagram/publishing.js";
10
+ import { registerIgMediaTools } from "./tools/instagram/media.js";
11
+ import { registerIgCommentTools } from "./tools/instagram/comments.js";
12
+ import { registerIgProfileTools } from "./tools/instagram/profile.js";
13
+ import { registerIgHashtagTools } from "./tools/instagram/hashtags.js";
14
+ import { registerIgMentionTools } from "./tools/instagram/mentions.js";
15
+ import { registerIgMessagingTools } from "./tools/instagram/messaging.js";
16
+ // Threads tools
17
+ import { registerThreadsPublishingTools } from "./tools/threads/publishing.js";
18
+ import { registerThreadsMediaTools } from "./tools/threads/media.js";
19
+ import { registerThreadsReplyTools } from "./tools/threads/replies.js";
20
+ import { registerThreadsProfileTools } from "./tools/threads/profile.js";
21
+ import { registerThreadsInsightTools } from "./tools/threads/insights.js";
22
+ // Resources & Prompts
23
+ import { registerInstagramResources } from "./resources/instagram.js";
24
+ import { registerThreadsResources } from "./resources/threads.js";
25
+ import { registerPrompts } from "./prompts/index.js";
26
+ const SERVER_VERSION = "3.0.0";
27
+ const server = new McpServer({
28
+ name: "meta-mcp",
29
+ version: SERVER_VERSION,
30
+ });
31
+ const config = loadConfig();
32
+ const client = new MetaClient(config);
33
+ // Register tools
34
+ registerMetaAuthTools(server, client);
35
+ registerIgPublishingTools(server, client);
36
+ registerIgMediaTools(server, client);
37
+ registerIgCommentTools(server, client);
38
+ registerIgProfileTools(server, client);
39
+ registerIgHashtagTools(server, client);
40
+ registerIgMentionTools(server, client);
41
+ registerIgMessagingTools(server, client);
42
+ registerThreadsPublishingTools(server, client);
43
+ registerThreadsMediaTools(server, client);
44
+ registerThreadsReplyTools(server, client);
45
+ registerThreadsProfileTools(server, client);
46
+ registerThreadsInsightTools(server, client);
47
+ // Register resources
48
+ registerInstagramResources(server, client);
49
+ registerThreadsResources(server, client);
50
+ // Register prompts
51
+ registerPrompts(server);
52
+ async function main() {
53
+ const transport = new StdioServerTransport();
54
+ await server.connect(transport);
55
+ }
56
+ main().catch((err) => {
57
+ console.error("Fatal error:", err);
58
+ process.exit(1);
59
+ });
60
+ // ── Smithery Sandbox ──
61
+ export function createSandboxServer() {
62
+ const sandbox = new McpServer({
63
+ name: "meta-mcp",
64
+ version: SERVER_VERSION,
65
+ });
66
+ const mockConfig = {
67
+ appId: "",
68
+ appSecret: "",
69
+ instagramAccessToken: "",
70
+ instagramUserId: "",
71
+ threadsAccessToken: "",
72
+ threadsUserId: "",
73
+ };
74
+ const mockClient = new MetaClient(mockConfig);
75
+ registerMetaAuthTools(sandbox, mockClient);
76
+ registerIgPublishingTools(sandbox, mockClient);
77
+ registerIgMediaTools(sandbox, mockClient);
78
+ registerIgCommentTools(sandbox, mockClient);
79
+ registerIgProfileTools(sandbox, mockClient);
80
+ registerIgHashtagTools(sandbox, mockClient);
81
+ registerIgMentionTools(sandbox, mockClient);
82
+ registerIgMessagingTools(sandbox, mockClient);
83
+ registerThreadsPublishingTools(sandbox, mockClient);
84
+ registerThreadsMediaTools(sandbox, mockClient);
85
+ registerThreadsReplyTools(sandbox, mockClient);
86
+ registerThreadsProfileTools(sandbox, mockClient);
87
+ registerThreadsInsightTools(sandbox, mockClient);
88
+ registerInstagramResources(sandbox, mockClient);
89
+ registerThreadsResources(sandbox, mockClient);
90
+ registerPrompts(sandbox);
91
+ return sandbox;
92
+ }
93
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerPrompts(server: McpServer): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,QAsEhD"}
@@ -0,0 +1,61 @@
1
+ export function registerPrompts(server) {
2
+ server.prompt("content_publish", "Cross-post content to Instagram and Threads simultaneously", {}, () => ({
3
+ messages: [
4
+ {
5
+ role: "user",
6
+ content: {
7
+ type: "text",
8
+ text: [
9
+ "Help me publish content across Instagram and Threads.",
10
+ "",
11
+ "Please follow these steps:",
12
+ "1. Ask me what content I want to post (text, image URL, video URL)",
13
+ "2. Use ig_publish_photo or ig_publish_video to post on Instagram",
14
+ "3. Use threads_publish_text, threads_publish_image, or threads_publish_video to post on Threads",
15
+ "4. Report back the permalink for each platform",
16
+ "",
17
+ "Tips:",
18
+ "- Instagram captions can be up to 2200 characters",
19
+ "- Threads posts are limited to 500 characters",
20
+ "- Both platforms require publicly accessible HTTPS URLs for media",
21
+ "- Video uploads may take time to process",
22
+ "- You can add alt_text for accessibility on both platforms",
23
+ "- On Threads, you can add a topic_tag, poll, or GIF attachment",
24
+ "- On Threads, you can set reply_control (everyone, accounts_you_follow, mentioned_only, parent_post_author_only, followers_only)",
25
+ ].join("\n"),
26
+ },
27
+ },
28
+ ],
29
+ }));
30
+ server.prompt("analytics_report", "Generate a combined analytics report for Instagram and Threads", {}, () => ({
31
+ messages: [
32
+ {
33
+ role: "user",
34
+ content: {
35
+ type: "text",
36
+ text: [
37
+ "Generate a comprehensive analytics report for my Instagram and Threads accounts.",
38
+ "",
39
+ "Please use the following tools:",
40
+ "1. ig_get_profile — Get Instagram profile stats (followers, media count)",
41
+ "2. ig_get_account_insights — Get Instagram insights for the last 7 days (metric: views,reach,follower_count, period: day)",
42
+ "3. ig_get_media_list — Get recent 10 posts to analyze engagement",
43
+ "4. threads_get_profile — Get Threads profile info",
44
+ "5. threads_get_user_insights — Get Threads insights (metric: views,likes,replies,reposts,quotes,clicks)",
45
+ "6. threads_get_posts — Get recent 10 Threads posts",
46
+ "",
47
+ "Then compile a report covering:",
48
+ "- Follower count and growth trends",
49
+ "- Top performing content on each platform",
50
+ "- Engagement rate comparison (likes, comments, shares)",
51
+ "- Recommendations for content strategy",
52
+ "",
53
+ "Note: 'impressions' and 'video_views' metrics were deprecated in Graph API v22.0.",
54
+ "Use 'views' and 'reach' instead.",
55
+ ].join("\n"),
56
+ },
57
+ },
58
+ ],
59
+ }));
60
+ }
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,MAAM,CAAC,MAAM,CACX,iBAAiB,EACjB,4DAA4D,EAC5D,EAAE,EACF,GAAG,EAAE,CAAC,CAAC;QACL,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;wBACJ,uDAAuD;wBACvD,EAAE;wBACF,4BAA4B;wBAC5B,oEAAoE;wBACpE,kEAAkE;wBAClE,iGAAiG;wBACjG,gDAAgD;wBAChD,EAAE;wBACF,OAAO;wBACP,mDAAmD;wBACnD,+CAA+C;wBAC/C,mEAAmE;wBACnE,0CAA0C;wBAC1C,4DAA4D;wBAC5D,gEAAgE;wBAChE,kIAAkI;qBACnI,CAAC,IAAI,CAAC,IAAI,CAAC;iBACb;aACF;SACF;KACF,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,MAAM,CACX,kBAAkB,EAClB,gEAAgE,EAChE,EAAE,EACF,GAAG,EAAE,CAAC,CAAC;QACL,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;wBACJ,kFAAkF;wBAClF,EAAE;wBACF,iCAAiC;wBACjC,0EAA0E;wBAC1E,2HAA2H;wBAC3H,kEAAkE;wBAClE,mDAAmD;wBACnD,yGAAyG;wBACzG,oDAAoD;wBACpD,EAAE;wBACF,iCAAiC;wBACjC,oCAAoC;wBACpC,2CAA2C;wBAC3C,wDAAwD;wBACxD,wCAAwC;wBACxC,EAAE;wBACF,mFAAmF;wBACnF,kCAAkC;qBACnC,CAAC,IAAI,CAAC,IAAI,CAAC;iBACb;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { MetaClient } from "../services/meta-client.js";
3
+ export declare function registerInstagramResources(server: McpServer, client: MetaClient): void;
4
+ //# sourceMappingURL=instagram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instagram.d.ts","sourceRoot":"","sources":["../../src/resources/instagram.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,QAoB/E"}
@@ -0,0 +1,17 @@
1
+ export function registerInstagramResources(server, client) {
2
+ server.resource("instagram-profile", "instagram://profile", { description: "Instagram Business/Creator account profile information", mimeType: "application/json" }, async () => {
3
+ const { data } = await client.ig("GET", `/${client.igUserId}`, {
4
+ fields: "id,name,username,biography,followers_count,follows_count,media_count,profile_picture_url,website",
5
+ });
6
+ return {
7
+ contents: [
8
+ {
9
+ uri: "instagram://profile",
10
+ mimeType: "application/json",
11
+ text: JSON.stringify(data, null, 2),
12
+ },
13
+ ],
14
+ };
15
+ });
16
+ }
17
+ //# sourceMappingURL=instagram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instagram.js","sourceRoot":"","sources":["../../src/resources/instagram.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,0BAA0B,CAAC,MAAiB,EAAE,MAAkB;IAC9E,MAAM,CAAC,QAAQ,CACb,mBAAmB,EACnB,qBAAqB,EACrB,EAAE,WAAW,EAAE,wDAAwD,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EACvG,KAAK,IAAI,EAAE;QACT,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE;YAC7D,MAAM,EAAE,kGAAkG;SAC3G,CAAC,CAAC;QACH,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,qBAAqB;oBAC1B,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { MetaClient } from "../services/meta-client.js";
3
+ export declare function registerThreadsResources(server: McpServer, client: MetaClient): void;
4
+ //# sourceMappingURL=threads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../src/resources/threads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,QAoB7E"}
@@ -0,0 +1,17 @@
1
+ export function registerThreadsResources(server, client) {
2
+ server.resource("threads-profile", "threads://profile", { description: "Threads user profile information", mimeType: "application/json" }, async () => {
3
+ const { data } = await client.threads("GET", `/${client.threadsUserId}`, {
4
+ fields: "id,username,name,threads_profile_picture_url,threads_biography,is_verified",
5
+ });
6
+ return {
7
+ contents: [
8
+ {
9
+ uri: "threads://profile",
10
+ mimeType: "application/json",
11
+ text: JSON.stringify(data, null, 2),
12
+ },
13
+ ],
14
+ };
15
+ });
16
+ }
17
+ //# sourceMappingURL=threads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threads.js","sourceRoot":"","sources":["../../src/resources/threads.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,wBAAwB,CAAC,MAAiB,EAAE,MAAkB;IAC5E,MAAM,CAAC,QAAQ,CACb,iBAAiB,EACjB,mBAAmB,EACnB,EAAE,WAAW,EAAE,kCAAkC,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EACjF,KAAK,IAAI,EAAE;QACT,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;YACvE,MAAM,EAAE,4EAA4E;SACrF,CAAC,CAAC;QACH,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,mBAAmB;oBACxB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}