@exileum/meta-mcp 4.0.0 → 6.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.
- package/README.md +81 -12
- package/dist/config.d.ts +10 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +65 -8
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/instagram.d.ts.map +1 -1
- package/dist/resources/instagram.js +19 -13
- package/dist/resources/instagram.js.map +1 -1
- package/dist/resources/threads.d.ts.map +1 -1
- package/dist/resources/threads.js +19 -13
- package/dist/resources/threads.js.map +1 -1
- package/dist/schemas.d.ts +14 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +14 -0
- package/dist/schemas.js.map +1 -1
- package/dist/services/meta-client.d.ts +47 -5
- package/dist/services/meta-client.d.ts.map +1 -1
- package/dist/services/meta-client.js +120 -27
- package/dist/services/meta-client.js.map +1 -1
- package/dist/tools/instagram/comments.d.ts.map +1 -1
- package/dist/tools/instagram/comments.js +35 -29
- package/dist/tools/instagram/comments.js.map +1 -1
- package/dist/tools/instagram/hashtags.d.ts.map +1 -1
- package/dist/tools/instagram/hashtags.js +19 -11
- package/dist/tools/instagram/hashtags.js.map +1 -1
- package/dist/tools/instagram/media.d.ts.map +1 -1
- package/dist/tools/instagram/media.js +17 -15
- package/dist/tools/instagram/media.js.map +1 -1
- package/dist/tools/instagram/mentions.d.ts.map +1 -1
- package/dist/tools/instagram/mentions.js +16 -12
- package/dist/tools/instagram/mentions.js.map +1 -1
- package/dist/tools/instagram/messaging.d.ts.map +1 -1
- package/dist/tools/instagram/messaging.js +34 -24
- package/dist/tools/instagram/messaging.js.map +1 -1
- package/dist/tools/instagram/profile.d.ts +2 -0
- package/dist/tools/instagram/profile.d.ts.map +1 -1
- package/dist/tools/instagram/profile.js +46 -21
- package/dist/tools/instagram/profile.js.map +1 -1
- package/dist/tools/instagram/publishing.d.ts.map +1 -1
- package/dist/tools/instagram/publishing.js +14 -13
- package/dist/tools/instagram/publishing.js.map +1 -1
- package/dist/tools/meta/auth.d.ts.map +1 -1
- package/dist/tools/meta/auth.js +7 -6
- package/dist/tools/meta/auth.js.map +1 -1
- package/dist/tools/threads/insights.d.ts.map +1 -1
- package/dist/tools/threads/insights.js +8 -8
- package/dist/tools/threads/insights.js.map +1 -1
- package/dist/tools/threads/media.d.ts.map +1 -1
- package/dist/tools/threads/media.js +12 -12
- package/dist/tools/threads/media.js.map +1 -1
- package/dist/tools/threads/mentions.d.ts.map +1 -1
- package/dist/tools/threads/mentions.js +2 -1
- package/dist/tools/threads/mentions.js.map +1 -1
- package/dist/tools/threads/profile.d.ts.map +1 -1
- package/dist/tools/threads/profile.js +2 -28
- package/dist/tools/threads/profile.js.map +1 -1
- package/dist/tools/threads/publishing.d.ts +7 -0
- package/dist/tools/threads/publishing.d.ts.map +1 -1
- package/dist/tools/threads/publishing.js +47 -35
- package/dist/tools/threads/publishing.js.map +1 -1
- package/dist/tools/threads/replies.d.ts +2 -0
- package/dist/tools/threads/replies.d.ts.map +1 -1
- package/dist/tools/threads/replies.js +32 -17
- package/dist/tools/threads/replies.js.map +1 -1
- package/dist/utils/container.d.ts +4 -2
- package/dist/utils/container.d.ts.map +1 -1
- package/dist/utils/container.js +8 -3
- package/dist/utils/container.js.map +1 -1
- package/dist/utils/errors.d.ts +38 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +145 -0
- package/dist/utils/errors.js.map +1 -0
- package/package.json +10 -1
package/README.md
CHANGED
|
@@ -64,11 +64,15 @@ npm run build
|
|
|
64
64
|
| Variable | Required | Description |
|
|
65
65
|
|----------|----------|-------------|
|
|
66
66
|
| `INSTAGRAM_ACCESS_TOKEN` | For Instagram | Instagram Graph API access token |
|
|
67
|
-
| `INSTAGRAM_USER_ID` | For Instagram | Instagram Business/Creator account ID |
|
|
67
|
+
| `INSTAGRAM_USER_ID` | For Instagram | Instagram Business/Creator account ID (numeric string, or `"me"` for the authenticated user) |
|
|
68
68
|
| `THREADS_ACCESS_TOKEN` | For Threads | Threads API access token |
|
|
69
|
-
| `THREADS_USER_ID` | For Threads | Threads user ID |
|
|
70
|
-
| `META_APP_ID` | For token/webhook tools | Meta App ID |
|
|
69
|
+
| `THREADS_USER_ID` | For Threads | Threads user ID (numeric string, or `"me"` for the authenticated user) |
|
|
70
|
+
| `META_APP_ID` | For token/webhook tools | Meta App ID (numeric string) |
|
|
71
71
|
| `META_APP_SECRET` | For token/webhook tools | Meta App Secret |
|
|
72
|
+
| `META_API_VERSION` | Optional | Meta Graph API version for Instagram and Facebook endpoints — defaults to `v25.0` (verified 2026-05-06). Override only when Meta deprecates a version before meta-mcp ships a new release. Format: `vMAJOR.MINOR` (e.g., `v26.0`); malformed values fall back to the default with a stderr warning. OAuth token endpoints are unversioned and unaffected by this setting |
|
|
73
|
+
| `THREADS_API_VERSION` | Optional | Threads API version — defaults to `v1.0` (verified 2026-05-06). Threads runs a separate single-major-version track and is not bumped in lockstep with the Graph API. Same `vMAJOR.MINOR` format and fallback behavior as `META_API_VERSION` |
|
|
74
|
+
|
|
75
|
+
The server validates these at startup. Malformed values for `INSTAGRAM_USER_ID`, `THREADS_USER_ID`, or `META_APP_ID` cause the process to exit with `Invalid meta-mcp configuration: …`. Setting only one half of a credential pair (e.g., `INSTAGRAM_ACCESS_TOKEN` without `INSTAGRAM_USER_ID`) prints a stderr warning and continues; related tool invocations still fail at call time.
|
|
72
76
|
|
|
73
77
|
## Account Requirements
|
|
74
78
|
|
|
@@ -80,13 +84,14 @@ npm run build
|
|
|
80
84
|
|
|
81
85
|
## Features
|
|
82
86
|
|
|
83
|
-
- **
|
|
87
|
+
- **58 tools** across Instagram (33), Threads (19), and Meta platform (6)
|
|
84
88
|
- **Instagram**: Publish photos/videos/reels/stories/carousels with alt text, manage comments, view insights, search hashtags, handle DMs, manage collaboration invites
|
|
85
89
|
- **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
|
|
86
90
|
- **Meta**: Token exchange/refresh/debug, webhook management
|
|
87
91
|
- **2 resources**: Instagram profile, Threads profile
|
|
88
92
|
- **2 prompts**: Cross-platform content publishing, analytics report
|
|
89
93
|
- Rate limit tracking via `x-app-usage` header
|
|
94
|
+
- **Structured error responses** with `error_type` (`auth`, `validation`, `rate_limit`, `server`, `network`, `internal`), HTTP status, Meta API code/subcode/type, and a `remediation` hint where actionable — see [`CHANGELOG.md`](./CHANGELOG.md) for the JSON shape
|
|
90
95
|
|
|
91
96
|
## Tools
|
|
92
97
|
|
|
@@ -139,10 +144,10 @@ npm run build
|
|
|
139
144
|
| Tool | Description |
|
|
140
145
|
|------|-------------|
|
|
141
146
|
| `ig_get_profile` | Get account profile info |
|
|
142
|
-
| `ig_get_account_insights` | Get account-level analytics (views, reach, follower_count) |
|
|
147
|
+
| `ig_get_account_insights` | Get account-level analytics (views, reach, follower_count). Optional `metric_type` (`total_value` or `time_series`) controls aggregation shape |
|
|
143
148
|
| `ig_business_discovery` | Look up another business account |
|
|
144
149
|
| `ig_get_collaboration_invites` | Get pending collaboration invites |
|
|
145
|
-
| `ig_respond_collaboration_invite` | Accept
|
|
150
|
+
| `ig_respond_collaboration_invite` | Accept/decline a collaboration invite by media_id |
|
|
146
151
|
|
|
147
152
|
### Instagram — Hashtags (4)
|
|
148
153
|
|
|
@@ -186,7 +191,7 @@ npm run build
|
|
|
186
191
|
|
|
187
192
|
| Tool | Description |
|
|
188
193
|
|------|-------------|
|
|
189
|
-
| `threads_get_posts` | List published posts (includes topic_tag, poll, GIF fields) |
|
|
194
|
+
| `threads_get_posts` | List published posts (includes topic_tag, poll, GIF fields; optional `fields` param to override the default field list) |
|
|
190
195
|
| `threads_get_post` | Get post details |
|
|
191
196
|
| `threads_search_posts` | Search public posts by keyword or tag (requires `threads_keyword_search` permission) |
|
|
192
197
|
|
|
@@ -205,12 +210,11 @@ npm run build
|
|
|
205
210
|
|------|-------------|
|
|
206
211
|
| `threads_get_mentions` | List posts where the user was @mentioned (requires `threads_manage_mentions`) |
|
|
207
212
|
|
|
208
|
-
### Threads — Profile (
|
|
213
|
+
### Threads — Profile (1)
|
|
209
214
|
|
|
210
215
|
| Tool | Description |
|
|
211
216
|
|------|-------------|
|
|
212
217
|
| `threads_get_profile` | Get Threads profile info (includes `is_verified` and `is_eligible_for_geo_gating`) |
|
|
213
|
-
| `threads_get_user_threads` | List user's threads |
|
|
214
218
|
|
|
215
219
|
### Threads — Insights (2)
|
|
216
220
|
|
|
@@ -223,8 +227,8 @@ npm run build
|
|
|
223
227
|
|
|
224
228
|
| Resource URI | Description |
|
|
225
229
|
|-------------|-------------|
|
|
226
|
-
| `instagram
|
|
227
|
-
| `threads
|
|
230
|
+
| `meta-mcp://instagram/profile` | Instagram account profile data |
|
|
231
|
+
| `meta-mcp://threads/profile` | Threads account profile data (includes is_verified) |
|
|
228
232
|
|
|
229
233
|
## Prompts
|
|
230
234
|
|
|
@@ -282,7 +286,7 @@ Your **`META_APP_ID`** and **`META_APP_SECRET`** are in **App Settings -> Basic*
|
|
|
282
286
|
https://threads.net/oauth/authorize
|
|
283
287
|
?client_id=YOUR_APP_ID
|
|
284
288
|
&redirect_uri=YOUR_REDIRECT_URI
|
|
285
|
-
&scope=threads_basic,threads_content_publish,threads_manage_insights,threads_manage_replies,threads_read_replies,threads_share_to_instagram,threads_manage_mentions
|
|
289
|
+
&scope=threads_basic,threads_content_publish,threads_manage_insights,threads_manage_replies,threads_read_replies,threads_share_to_instagram,threads_manage_mentions,threads_keyword_search
|
|
286
290
|
&response_type=code
|
|
287
291
|
```
|
|
288
292
|
For local testing, use `https://localhost/` as redirect URI (configure in App Settings -> Threads API -> Redirect URIs).
|
|
@@ -329,10 +333,75 @@ Access tokens expire after ~60 days. Refresh before expiration (token must be at
|
|
|
329
333
|
|
|
330
334
|
Check token status anytime with `meta_debug_token`.
|
|
331
335
|
|
|
336
|
+
## Troubleshooting
|
|
337
|
+
|
|
338
|
+
Tool failures return `isError: true` with a JSON body in `content[0].text` matching the envelope documented in [`CHANGELOG.md`](./CHANGELOG.md): `{ error: true, error_type, http_status, code, subcode, type, message, remediation, fbtrace_id, raw }`. The fastest path to a fix is to read `error_type` and the Meta API `code`, then jump to the matching subsection below. The full code reference is the [Meta Graph API error handling guide](https://developers.facebook.com/docs/graph-api/guides/error-handling/).
|
|
339
|
+
|
|
340
|
+
### `error_type: "auth"` — expired, revoked, or under-scoped token
|
|
341
|
+
|
|
342
|
+
Triggered by Meta API codes `190`, `10`, `102`, HTTP `401`, or `type: "OAuthException"`. Common messages:
|
|
343
|
+
|
|
344
|
+
- `Error validating access token: Session has expired` — long-lived tokens expire ~60 days after issue.
|
|
345
|
+
- `Application does not have permission for this action` — the token is missing a scope, or the account is not eligible (e.g., a **Personal** Instagram account on Graph API endpoints).
|
|
346
|
+
|
|
347
|
+
What to do:
|
|
348
|
+
|
|
349
|
+
1. Run `meta_debug_token` to inspect `expires_at`, `is_valid`, and `scopes`.
|
|
350
|
+
2. If the token is **not yet expired** but at least 24h old, refresh in place with `meta_refresh_token` (`platform: "instagram"` or `"threads"`) — this extends the lifetime by another ~60 days. If the token is **already expired**, the refresh endpoint will reject it; regenerate a short-lived token from the Meta App dashboard and exchange it via `meta_exchange_token` (or run a full re-authorization for Threads).
|
|
351
|
+
3. If scopes are missing, regenerate the token with the required permissions:
|
|
352
|
+
- **Instagram**: `instagram_business_basic` (always required) plus `instagram_business_content_publish`, `instagram_business_manage_comments`, `instagram_business_manage_messages` per feature.
|
|
353
|
+
- **Threads**: `threads_basic`, `threads_content_publish`, `threads_manage_insights`, `threads_manage_replies`, `threads_read_replies`, `threads_share_to_instagram`, `threads_manage_mentions`, `threads_keyword_search` per feature.
|
|
354
|
+
4. If your Instagram account is **Personal**, switch to **Business** or **Creator** for free in the Instagram app (Settings → Account type and tools → Switch to professional account). The Graph API rejects Personal accounts.
|
|
355
|
+
|
|
356
|
+
### `error_type: "rate_limit"` — application or user quota exhausted
|
|
357
|
+
|
|
358
|
+
Triggered by Meta API codes `4`, `17`, `32`, `341`, `613`, the business-use-case range `80001`–`80008`, or HTTP `429`. Includes any `OAuthException` with code `4` / `17` (these are surfaced as `error_type: "rate_limit"`, **not** `"auth"`, despite the type field).
|
|
359
|
+
|
|
360
|
+
What to do:
|
|
361
|
+
|
|
362
|
+
1. Inspect the `_rateLimit` field on prior successful tool responses. `callCount`, `totalCpuTime`, and `totalTime` come from Meta's `x-app-usage` header; when `callCount` approaches `100` you are near the per-app threshold.
|
|
363
|
+
2. Back off with exponential delay; reduce request volume; cache profile metadata between calls.
|
|
364
|
+
3. Threads has hard daily quotas (250 publishes, 100 deletes) — query the remaining quota with `threads_get_publishing_limit` before bulk operations.
|
|
365
|
+
|
|
366
|
+
### `error_type: "validation"` — bad parameter, wrong ID, or unsupported field
|
|
367
|
+
|
|
368
|
+
Triggered by Meta API codes `100`, `200`, `803`, or any unmapped 4xx HTTP status. Common pitfalls:
|
|
369
|
+
|
|
370
|
+
- **Wrong user ID format** — `INSTAGRAM_USER_ID` and `THREADS_USER_ID` must be the **numeric ID** returned by `GET /me?fields=user_id` (Instagram) or `GET /me?fields=id` (Threads), or the literal `"me"` for the authenticated user. The Instagram **username** is not accepted.
|
|
371
|
+
- **`(#100) Messaging is not supported`** on `ig_send_message` / `ig_get_conversations` / `ig_get_messages` — the account does not have the messaging API enabled. Grant `instagram_business_manage_messages` on your token and ensure DMs are enabled in the Instagram app (Settings → Privacy → Messages).
|
|
372
|
+
- **Deprecated publish endpoint** — `ig_publish_video` was retired by Meta on Nov 9, 2023; use `ig_publish_reel` for video posts. `ig_publish_story` is required for Stories.
|
|
373
|
+
- **Mutually exclusive Threads attachments** — a `threads_publish_text` post can carry only one of `text_attachment`, `poll_options`, `link_attachment`, or `gif_attachment`; combining them is rejected at the schema level.
|
|
374
|
+
- **Unsupported `metric` / `fields` for the resource** — see the per-tool Meta docs (`ig_get_media_insights` lists per-`media_type` valid metrics in its description).
|
|
375
|
+
|
|
376
|
+
### Other categories
|
|
377
|
+
|
|
378
|
+
- `error_type: "server"` (codes `1`, `2`, HTTP 5xx) — transient Meta outage; retry with exponential backoff. Check [metastatus.com](https://metastatus.com/) if it persists.
|
|
379
|
+
- `error_type: "network"` — `fetch` timed out or failed before reaching Meta. Verify outbound connectivity and retry.
|
|
380
|
+
- `error_type: "internal"` — unexpected condition that did not map to a Meta error code. The `raw` field carries the sanitized original message; `access_token`, `client_secret`, and `input_token` values are scrubbed to `***` before reporting.
|
|
381
|
+
|
|
382
|
+
## API Stability
|
|
383
|
+
|
|
384
|
+
meta-mcp is consumed as an **MCP server runtime**, not as a library. The supported entry points are:
|
|
385
|
+
|
|
386
|
+
- `npx @exileum/meta-mcp` (recommended for end users)
|
|
387
|
+
- `node dist/index.js` (manual installation)
|
|
388
|
+
|
|
389
|
+
The single programmatic export from the package root, `createSandboxServer(): McpServer`, exists for the [Smithery](https://smithery.ai) sandbox runner and is the only stable JavaScript/TypeScript API.
|
|
390
|
+
|
|
391
|
+
**`zod` and other transitive runtime dependencies are internal** and not part of meta-mcp's public API. No `zod` symbols, types, or schemas flow through `dist/index.d.ts`, so `zod`'s version may change in any release — including major version bumps — without a corresponding meta-mcp major bump.
|
|
392
|
+
|
|
393
|
+
**`@modelcontextprotocol/sdk` is the one exception**: `McpServer` (the return type of `createSandboxServer()`) is imported from that package, so a breaking change to `McpServer`'s public interface would also be a breaking change for meta-mcp's programmatic API. In practice the MCP SDK follows semver, so consumers can treat `@modelcontextprotocol/sdk` as an implicit peer dependency of the `createSandboxServer` export.
|
|
394
|
+
|
|
395
|
+
Only the package root (`@exileum/meta-mcp`) is a supported import target. Deep imports into the published `dist/` tree (e.g. `@exileum/meta-mcp/dist/schemas.js`) are blocked by the `package.json` `exports` map for any spec-compliant resolver and are **not** part of the public API; they may be renamed, removed, or restructured in any release.
|
|
396
|
+
|
|
332
397
|
## Glama
|
|
333
398
|
|
|
334
399
|
[](https://glama.ai/mcp/servers/exileum/meta-mcp)
|
|
335
400
|
|
|
401
|
+
## Contributing
|
|
402
|
+
|
|
403
|
+
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the dev setup, project layout, the tool-registration recipe, testing, commit conventions, the CHANGELOG flow, and the CI gates. Bug reports and feature requests use the [issue templates](.github/ISSUE_TEMPLATE); pull requests use the [PR template](.github/PULL_REQUEST_TEMPLATE.md).
|
|
404
|
+
|
|
336
405
|
## License
|
|
337
406
|
|
|
338
407
|
[MIT](LICENSE)
|
package/dist/config.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const MetaConfigSchema: z.ZodObject<{
|
|
3
|
+
appId: z.ZodDefault<z.ZodString>;
|
|
4
|
+
appSecret: z.ZodDefault<z.ZodString>;
|
|
5
|
+
instagramAccessToken: z.ZodDefault<z.ZodString>;
|
|
6
|
+
instagramUserId: z.ZodDefault<z.ZodString>;
|
|
7
|
+
threadsAccessToken: z.ZodDefault<z.ZodString>;
|
|
8
|
+
threadsUserId: z.ZodDefault<z.ZodString>;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
export type MetaConfig = z.infer<typeof MetaConfigSchema>;
|
|
9
11
|
export declare function loadConfig(): MetaConfig;
|
|
10
12
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsBxB,eAAO,MAAM,gBAAgB;;;;;;;iBAO3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,wBAAgB,UAAU,IAAI,UAAU,CAiBvC"}
|
package/dist/config.js
CHANGED
|
@@ -1,11 +1,68 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Regex `*` (zero-or-more) is intentional so the Zod `.default("")` for unset
|
|
3
|
+
// vars passes validation; an empty string is treated as "absent" by warning
|
|
4
|
+
// logic and by the lazy "X is not configured" runtime checks in MetaClient.
|
|
5
|
+
const appIdSchema = z
|
|
6
|
+
.string()
|
|
7
|
+
.regex(/^\d*$/, "META_APP_ID must be a numeric string")
|
|
8
|
+
.default("");
|
|
9
|
+
// User IDs accept either a numeric string or the literal "me" — Meta's
|
|
10
|
+
// Graph/Threads APIs accept "me" as the authenticated-user alias on
|
|
11
|
+
// `/{user-id}/...` paths (e.g., GET https://graph.threads.net/v1.0/me).
|
|
12
|
+
const userIdSchema = (envName) => z
|
|
13
|
+
.string()
|
|
14
|
+
.regex(/^(me|\d*)$/, `${envName} must be a numeric string or "me"`)
|
|
15
|
+
.default("");
|
|
16
|
+
export const MetaConfigSchema = z.object({
|
|
17
|
+
appId: appIdSchema,
|
|
18
|
+
appSecret: z.string().default(""),
|
|
19
|
+
instagramAccessToken: z.string().default(""),
|
|
20
|
+
instagramUserId: userIdSchema("INSTAGRAM_USER_ID"),
|
|
21
|
+
threadsAccessToken: z.string().default(""),
|
|
22
|
+
threadsUserId: userIdSchema("THREADS_USER_ID"),
|
|
23
|
+
});
|
|
1
24
|
export function loadConfig() {
|
|
2
|
-
|
|
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
|
-
};
|
|
25
|
+
const result = MetaConfigSchema.safeParse({
|
|
26
|
+
appId: process.env.META_APP_ID,
|
|
27
|
+
appSecret: process.env.META_APP_SECRET,
|
|
28
|
+
instagramAccessToken: process.env.INSTAGRAM_ACCESS_TOKEN,
|
|
29
|
+
instagramUserId: process.env.INSTAGRAM_USER_ID,
|
|
30
|
+
threadsAccessToken: process.env.THREADS_ACCESS_TOKEN,
|
|
31
|
+
threadsUserId: process.env.THREADS_USER_ID,
|
|
32
|
+
});
|
|
33
|
+
if (!result.success) {
|
|
34
|
+
const issues = result.error.issues.map((i) => ` - ${i.message}`).join("\n");
|
|
35
|
+
throw new Error(`Invalid meta-mcp configuration:\n${issues}`);
|
|
36
|
+
}
|
|
37
|
+
warnIfMisconfigured(result.data);
|
|
38
|
+
return result.data;
|
|
39
|
+
}
|
|
40
|
+
function warnIfMisconfigured(config) {
|
|
41
|
+
const noCredentials = Object.values(config).every((v) => !v);
|
|
42
|
+
if (noCredentials) {
|
|
43
|
+
console.error("[meta-mcp] Warning: no credentials configured — every tool invocation will fail until you set INSTAGRAM_ACCESS_TOKEN, THREADS_ACCESS_TOKEN, or META_APP_ID/META_APP_SECRET.");
|
|
44
|
+
}
|
|
45
|
+
const pairs = [
|
|
46
|
+
[
|
|
47
|
+
!!config.instagramAccessToken,
|
|
48
|
+
!!config.instagramUserId,
|
|
49
|
+
"INSTAGRAM_ACCESS_TOKEN",
|
|
50
|
+
"INSTAGRAM_USER_ID",
|
|
51
|
+
],
|
|
52
|
+
[
|
|
53
|
+
!!config.threadsAccessToken,
|
|
54
|
+
!!config.threadsUserId,
|
|
55
|
+
"THREADS_ACCESS_TOKEN",
|
|
56
|
+
"THREADS_USER_ID",
|
|
57
|
+
],
|
|
58
|
+
[!!config.appId, !!config.appSecret, "META_APP_ID", "META_APP_SECRET"],
|
|
59
|
+
];
|
|
60
|
+
for (const [hasA, hasB, aName, bName] of pairs) {
|
|
61
|
+
if (hasA === hasB)
|
|
62
|
+
continue;
|
|
63
|
+
const setName = hasA ? aName : bName;
|
|
64
|
+
const missingName = hasA ? bName : aName;
|
|
65
|
+
console.error(`[meta-mcp] Warning: ${setName} is set but ${missingName} is missing — related tools will fail at invocation time.`);
|
|
66
|
+
}
|
|
10
67
|
}
|
|
11
68
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkFpE,wBAAgB,mBAAmB,cAmClC"}
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,14 @@ const server = new McpServer({
|
|
|
31
31
|
name: "meta-mcp",
|
|
32
32
|
version: SERVER_VERSION,
|
|
33
33
|
});
|
|
34
|
-
|
|
34
|
+
let config;
|
|
35
|
+
try {
|
|
36
|
+
config = loadConfig();
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
35
42
|
const client = new MetaClient(config);
|
|
36
43
|
// Register tools
|
|
37
44
|
registerMetaAuthTools(server, client);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvD,sBAAsB;AACtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,kBAAkB;AAClB,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,gBAAgB;AAChB,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAE3E,sBAAsB;AACtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AAEtF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,cAAc;CACxB,CAAC,CAAC;AAEH,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +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;
|
|
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;AAGxD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,QAwB/E"}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
|
+
import { toMcpResourceError } from "../utils/errors.js";
|
|
1
2
|
export function registerInstagramResources(server, client) {
|
|
2
|
-
server.resource("instagram-profile", "instagram
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
server.resource("instagram-profile", "meta-mcp://instagram/profile", { description: "Instagram Business/Creator account profile information", mimeType: "application/json" }, async () => {
|
|
4
|
+
try {
|
|
5
|
+
const { data } = await client.ig("GET", `/${client.igUserId}`, {
|
|
6
|
+
fields: "id,name,username,biography,followers_count,follows_count,media_count,profile_picture_url,website",
|
|
7
|
+
});
|
|
8
|
+
return {
|
|
9
|
+
contents: [
|
|
10
|
+
{
|
|
11
|
+
uri: "meta-mcp://instagram/profile",
|
|
12
|
+
mimeType: "application/json",
|
|
13
|
+
text: JSON.stringify(data, null, 2),
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
throw toMcpResourceError(error, "Get Instagram profile");
|
|
20
|
+
}
|
|
15
21
|
});
|
|
16
22
|
}
|
|
17
23
|
//# sourceMappingURL=instagram.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instagram.js","sourceRoot":"","sources":["../../src/resources/instagram.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"instagram.js","sourceRoot":"","sources":["../../src/resources/instagram.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,0BAA0B,CAAC,MAAiB,EAAE,MAAkB;IAC9E,MAAM,CAAC,QAAQ,CACb,mBAAmB,EACnB,8BAA8B,EAC9B,EAAE,WAAW,EAAE,wDAAwD,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EACvG,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE;gBAC7D,MAAM,EAAE,kGAAkG;aAC3G,CAAC,CAAC;YACH,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,8BAA8B;wBACnC,QAAQ,EAAE,kBAAkB;wBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;qBACpC;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +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;
|
|
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;AAGxD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,QAwB7E"}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
|
+
import { toMcpResourceError } from "../utils/errors.js";
|
|
1
2
|
export function registerThreadsResources(server, client) {
|
|
2
|
-
server.resource("threads-profile", "threads
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
server.resource("threads-profile", "meta-mcp://threads/profile", { description: "Threads user profile information", mimeType: "application/json" }, async () => {
|
|
4
|
+
try {
|
|
5
|
+
const { data } = await client.threads("GET", `/${client.threadsUserId}`, {
|
|
6
|
+
fields: "id,username,name,threads_profile_picture_url,threads_biography,is_verified",
|
|
7
|
+
});
|
|
8
|
+
return {
|
|
9
|
+
contents: [
|
|
10
|
+
{
|
|
11
|
+
uri: "meta-mcp://threads/profile",
|
|
12
|
+
mimeType: "application/json",
|
|
13
|
+
text: JSON.stringify(data, null, 2),
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
throw toMcpResourceError(error, "Get Threads profile");
|
|
20
|
+
}
|
|
15
21
|
});
|
|
16
22
|
}
|
|
17
23
|
//# sourceMappingURL=threads.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"threads.js","sourceRoot":"","sources":["../../src/resources/threads.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"threads.js","sourceRoot":"","sources":["../../src/resources/threads.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,wBAAwB,CAAC,MAAiB,EAAE,MAAkB;IAC5E,MAAM,CAAC,QAAQ,CACb,iBAAiB,EACjB,4BAA4B,EAC5B,EAAE,WAAW,EAAE,kCAAkC,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EACjF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;gBACvE,MAAM,EAAE,4EAA4E;aACrF,CAAC,CAAC;YACH,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,4BAA4B;wBACjC,QAAQ,EAAE,kBAAkB;wBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;qBACpC;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/dist/schemas.d.ts
CHANGED
|
@@ -4,4 +4,18 @@ import { z } from "zod";
|
|
|
4
4
|
* Use for all user-provided media and callback URLs to prevent SSRF and non-secure schemes.
|
|
5
5
|
*/
|
|
6
6
|
export declare const httpsUrl: z.ZodString;
|
|
7
|
+
/**
|
|
8
|
+
* Zod schema for Meta-issued resource IDs (media, comment, container, post,
|
|
9
|
+
* reply, conversation, message, hashtag). Use for any ID that gets interpolated
|
|
10
|
+
* into a URL path segment in MetaClient calls — rejects path-altering characters
|
|
11
|
+
* (`/`, `.`, `?`, `&`, `=`, whitespace) at schema parse time so a crafted value
|
|
12
|
+
* cannot rewrite the request path or inject query params. The `+` quantifier
|
|
13
|
+
* also enforces non-empty (callers chaining `.min(1)` is redundant).
|
|
14
|
+
*
|
|
15
|
+
* Real Meta IDs are numeric (e.g. `17889615324123`) or numeric-with-underscore
|
|
16
|
+
* for compound containers (e.g. `17841405822304914_17889615324123`); the
|
|
17
|
+
* `[a-zA-Z0-9_-]` set is intentionally broader to absorb future format changes
|
|
18
|
+
* while keeping path-traversal characters out.
|
|
19
|
+
*/
|
|
20
|
+
export declare const metaId: z.ZodString;
|
|
7
21
|
//# sourceMappingURL=schemas.d.ts.map
|
package/dist/schemas.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,QAAQ,aAGpB,CAAC"}
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,QAAQ,aAGpB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,aAGlB,CAAC"}
|
package/dist/schemas.js
CHANGED
|
@@ -4,4 +4,18 @@ import { z } from "zod";
|
|
|
4
4
|
* Use for all user-provided media and callback URLs to prevent SSRF and non-secure schemes.
|
|
5
5
|
*/
|
|
6
6
|
export const httpsUrl = z.string().url().refine((u) => u.toLowerCase().startsWith("https://"), { message: "URL must use HTTPS" });
|
|
7
|
+
/**
|
|
8
|
+
* Zod schema for Meta-issued resource IDs (media, comment, container, post,
|
|
9
|
+
* reply, conversation, message, hashtag). Use for any ID that gets interpolated
|
|
10
|
+
* into a URL path segment in MetaClient calls — rejects path-altering characters
|
|
11
|
+
* (`/`, `.`, `?`, `&`, `=`, whitespace) at schema parse time so a crafted value
|
|
12
|
+
* cannot rewrite the request path or inject query params. The `+` quantifier
|
|
13
|
+
* also enforces non-empty (callers chaining `.min(1)` is redundant).
|
|
14
|
+
*
|
|
15
|
+
* Real Meta IDs are numeric (e.g. `17889615324123`) or numeric-with-underscore
|
|
16
|
+
* for compound containers (e.g. `17841405822304914_17889615324123`); the
|
|
17
|
+
* `[a-zA-Z0-9_-]` set is intentionally broader to absorb future format changes
|
|
18
|
+
* while keeping path-traversal characters out.
|
|
19
|
+
*/
|
|
20
|
+
export const metaId = z.string().regex(/^[a-zA-Z0-9_-]+$/, "ID must contain only letters, numbers, underscores, and hyphens");
|
|
7
21
|
//# sourceMappingURL=schemas.js.map
|
package/dist/schemas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,CAC7C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAC7C,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAClC,CAAC"}
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,CAC7C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAC7C,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAClC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CACpC,kBAAkB,EAClB,iEAAiE,CAClE,CAAC"}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { MetaConfig } from "../config.js";
|
|
2
|
+
export declare const DEFAULT_META_API_VERSION = "v25.0";
|
|
3
|
+
export declare const DEFAULT_THREADS_API_VERSION = "v1.0";
|
|
4
|
+
export interface MetaClientOptions {
|
|
5
|
+
metaApiVersion?: string;
|
|
6
|
+
threadsApiVersion?: string;
|
|
7
|
+
}
|
|
2
8
|
export interface RateLimit {
|
|
3
9
|
callCount?: number;
|
|
4
10
|
totalCpuTime?: number;
|
|
@@ -8,17 +14,53 @@ export interface ClientResponse {
|
|
|
8
14
|
data: Record<string, unknown>;
|
|
9
15
|
rateLimit?: RateLimit;
|
|
10
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Allowed value types for form-encoded query string and request body parameters.
|
|
19
|
+
* Non-primitive values (arrays, objects) must be serialized by the caller (JSON.stringify, .join(",") etc.)
|
|
20
|
+
* before being assigned — the form-encoded path uses String(v) which produces "[object Object]" / "1,2,3"
|
|
21
|
+
* for objects/arrays and silently corrupts the request.
|
|
22
|
+
*/
|
|
23
|
+
export type FormParamValue = string | number | boolean | undefined | null;
|
|
24
|
+
export type FormParams = Record<string, FormParamValue>;
|
|
11
25
|
export interface RequestOptions {
|
|
12
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Sends the value as an `application/json` request body instead of the default
|
|
28
|
+
* `application/x-www-form-urlencoded`. The `access_token` is moved to the query
|
|
29
|
+
* string (never embedded in the JSON body) and `params` must be omitted —
|
|
30
|
+
* combining them is rejected at runtime so callers don't accidentally route
|
|
31
|
+
* data into both transports.
|
|
32
|
+
*
|
|
33
|
+
* **When to use:** only when Meta's documentation explicitly requires
|
|
34
|
+
* `Content-Type: application/json` for the endpoint. Currently the
|
|
35
|
+
* Instagram Messaging Send API (`POST /{ig-user-id}/messages`, used by
|
|
36
|
+
* `ig_send_message`) is the only such endpoint — it accepts nested
|
|
37
|
+
* `recipient` / `message` objects that would be flattened to
|
|
38
|
+
* `[object Object]` if sent through the form path. See
|
|
39
|
+
* https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/messaging-api
|
|
40
|
+
*
|
|
41
|
+
* **When not to use:** every other Graph API endpoint (Threads publish,
|
|
42
|
+
* Instagram media/comments/collaboration, Meta App Subscriptions, etc.)
|
|
43
|
+
* accepts form-urlencoded with flat string/number/boolean parameters and
|
|
44
|
+
* works correctly through the default path. Nested objects required by the
|
|
45
|
+
* API (`poll_attachment`, `gif_attachment`, `text_attachment`, `user_tags`)
|
|
46
|
+
* must be `JSON.stringify`-ed by the caller into a single form field — the
|
|
47
|
+
* runtime guard in `appendFormParams` rejects raw objects/arrays so this
|
|
48
|
+
* convention is enforced (see #81). Audited in #104.
|
|
49
|
+
*/
|
|
50
|
+
jsonBody?: Record<string, unknown>;
|
|
13
51
|
}
|
|
14
52
|
export declare class MetaClient {
|
|
15
53
|
private config;
|
|
16
|
-
|
|
54
|
+
private igBase;
|
|
55
|
+
private fbBase;
|
|
56
|
+
private threadsBase;
|
|
57
|
+
constructor(config: MetaConfig, options?: MetaClientOptions);
|
|
17
58
|
private parseRateLimit;
|
|
59
|
+
private appendFormParams;
|
|
18
60
|
private request;
|
|
19
|
-
ig(method: string, path: string, params?:
|
|
20
|
-
threads(method: string, path: string, params?:
|
|
21
|
-
meta(method: string, path: string, params?:
|
|
61
|
+
ig(method: string, path: string, params?: FormParams, options?: RequestOptions): Promise<ClientResponse>;
|
|
62
|
+
threads(method: string, path: string, params?: FormParams, options?: RequestOptions): Promise<ClientResponse>;
|
|
63
|
+
meta(method: string, path: string, params?: FormParams, options?: RequestOptions): Promise<ClientResponse>;
|
|
22
64
|
/** Exchange short-lived Instagram token for long-lived token (60 days) */
|
|
23
65
|
igExchangeToken(shortToken: string): Promise<ClientResponse>;
|
|
24
66
|
/** Refresh a long-lived Instagram token (must be at least 24h old and not expired) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meta-client.d.ts","sourceRoot":"","sources":["../../src/services/meta-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"meta-client.d.ts","sourceRoot":"","sources":["../../src/services/meta-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAa1C,eAAO,MAAM,wBAAwB,UAAU,CAAC;AAChD,eAAO,MAAM,2BAA2B,SAAS,CAAC;AA8BlD,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;AAC1E,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AA4BD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAS;gBAEhB,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,iBAAiB;IAiB3D,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,gBAAgB;YAeV,OAAO;IAuFf,EAAE,CACN,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,UAAU,EACnB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC;IAOpB,OAAO,CACX,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,UAAU,EACnB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC;IAOpB,IAAI,CACR,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,UAAU,EACnB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,cAAc,CAAC;IAQ1B,0EAA0E;IACpE,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAUlE,sFAAsF;IAChF,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAMhE,wEAAwE;IAClE,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAUvE,oFAAoF;IAC9E,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAMrE,oBAAoB;IACd,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAU7D,IAAI,QAAQ,IAAI,MAAM,CAKrB;IAED,IAAI,aAAa,IAAI,MAAM,CAK1B;CACF"}
|