@praise25/meta-mcp-server 0.1.8 → 0.1.11
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/LICENSE +21 -21
- package/README.md +292 -292
- package/dist/config.d.ts +24 -0
- package/dist/config.js +14 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/helpers/graph-client.d.ts +11 -1
- package/dist/helpers/graph-client.js +24 -16
- package/dist/index.js +0 -0
- package/dist/server.js +21 -1
- package/dist/tools/ads/get-insights.d.ts +1 -1
- package/dist/tools/ads/get-insights.js +12 -10
- package/dist/tools/ads/list-accounts.js +4 -4
- package/dist/tools/business/list-assets.js +10 -10
- package/dist/tools/business/list-businesses.js +4 -4
- package/dist/tools/business/list-system-users.js +4 -4
- package/dist/tools/instagram/get-audience-demographics.d.ts +5 -1
- package/dist/tools/instagram/get-audience-demographics.js +17 -10
- package/dist/tools/instagram/get-media-insights.js +14 -14
- package/dist/tools/instagram/list-accounts.js +2 -2
- package/dist/tools/meta/graph-read.js +7 -7
- package/dist/tools/overview/business-overview.js +10 -10
- package/dist/tools/overview/content-report.d.ts +57 -0
- package/dist/tools/overview/content-report.js +344 -0
- package/dist/tools/overview/latest-posts-summary.d.ts +1 -1
- package/dist/tools/overview/latest-posts-summary.js +10 -16
- package/dist/tools/pages/get-insights.js +2 -2
- package/dist/tools/pages/get-post-insights.js +4 -4
- package/dist/tools/pages/list-posts.d.ts +1 -1
- package/dist/tools/pages/list-posts.js +3 -1
- package/dist/tools/register.js +3 -2
- package/dist/tools/shared.d.ts +19 -4
- package/dist/tools/shared.js +56 -0
- package/dist/tools/token/health.js +8 -6
- package/dist/tools/token/inspect.js +11 -11
- package/dist/tools/whatsapp/get-analytics.js +2 -2
- package/package.json +77 -77
package/dist/tools/shared.js
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers used across domain tools — keeps each tool file focused on
|
|
3
|
+
* its endpoint instead of re-implementing boilerplate.
|
|
4
|
+
*/
|
|
5
|
+
import { insightsCreds } from "../config.js";
|
|
1
6
|
import { MetaError } from "../errors.js";
|
|
2
7
|
import { jsonBlock, toolError, toolResult } from "../helpers/format.js";
|
|
8
|
+
/**
|
|
9
|
+
* If a secondary "insights app" is configured, returns the token + app-secret
|
|
10
|
+
* overrides to route this call through it; otherwise returns an empty object
|
|
11
|
+
* (call uses the primary app). Insight endpoints (IG media/audience, Page/post
|
|
12
|
+
* insights) need this because Meta forbids combining the Marketing-API use
|
|
13
|
+
* case with Instagram-content / Pages-everything on a single app — so insights
|
|
14
|
+
* frequently live on a second app. See config.ts `insightsCreds`.
|
|
15
|
+
*/
|
|
16
|
+
function insightsOverrides(ctx) {
|
|
17
|
+
const creds = insightsCreds(ctx.config);
|
|
18
|
+
if (!creds)
|
|
19
|
+
return {};
|
|
20
|
+
return { accessTokenOverride: creds.token, appSecretOverride: creds.appSecret };
|
|
21
|
+
}
|
|
3
22
|
/**
|
|
4
23
|
* Fetch one page or auto-paginate, normalize into a structured list payload,
|
|
5
24
|
* and translate errors. Use for simple `GET /{id}/{edge}` style tools.
|
|
@@ -43,6 +62,16 @@ export async function runGet(ctx, opts, extra = {}) {
|
|
|
43
62
|
return errorResult(err);
|
|
44
63
|
}
|
|
45
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Like runGet, but routes through the secondary insights-app token + secret
|
|
67
|
+
* when one is configured (META_INSIGHTS_ACCESS_TOKEN). Use for direct
|
|
68
|
+
* `/{id}/insights` reads that require a permission (e.g.
|
|
69
|
+
* instagram_manage_insights) the primary ads app cannot host. Falls back to
|
|
70
|
+
* the primary token transparently when no insights app is configured.
|
|
71
|
+
*/
|
|
72
|
+
export async function runGetViaInsightsApp(ctx, opts, extra = {}) {
|
|
73
|
+
return runGet(ctx, { ...opts, ...insightsOverrides(ctx) }, extra);
|
|
74
|
+
}
|
|
46
75
|
export function errorResult(err) {
|
|
47
76
|
const e = err instanceof MetaError ? err : new MetaError(err.message);
|
|
48
77
|
return toolError(e.message, e.hint, {
|
|
@@ -79,3 +108,30 @@ export async function runGetAsPage(ctx, pageId, opts, extra = {}) {
|
|
|
79
108
|
return errorResult(err);
|
|
80
109
|
}
|
|
81
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Page-insights variant of runGetAsPage. When a secondary insights app is
|
|
113
|
+
* configured (the app holding the Pages "read_insights" use case), the Page
|
|
114
|
+
* access token is derived from the *insights* app's token and the call's
|
|
115
|
+
* appsecret_proof uses the insights app secret. Falls back to the primary
|
|
116
|
+
* app's Page token when no insights app is configured.
|
|
117
|
+
*
|
|
118
|
+
* Use for /{page_id}/insights and /{post_id}/insights, which need
|
|
119
|
+
* `read_insights` — a permission the Marketing-API primary app cannot host.
|
|
120
|
+
*/
|
|
121
|
+
export async function runGetAsPageViaInsightsApp(ctx, pageId, opts, extra = {}) {
|
|
122
|
+
try {
|
|
123
|
+
const creds = insightsCreds(ctx.config);
|
|
124
|
+
if (creds) {
|
|
125
|
+
const pageToken = await ctx.graph.getPageAccessToken(pageId, {
|
|
126
|
+
token: creds.token,
|
|
127
|
+
appSecret: creds.appSecret,
|
|
128
|
+
});
|
|
129
|
+
return runGet(ctx, { ...opts, accessTokenOverride: pageToken, appSecretOverride: creds.appSecret }, extra);
|
|
130
|
+
}
|
|
131
|
+
const pageToken = await ctx.graph.getPageAccessToken(pageId);
|
|
132
|
+
return runGet(ctx, { ...opts, accessTokenOverride: pageToken }, extra);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
return errorResult(err);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -5,12 +5,12 @@ export const inputSchema = z.object({}).strict();
|
|
|
5
5
|
export const definition = {
|
|
6
6
|
name: "meta_health_check",
|
|
7
7
|
title: "Meta MCP health check",
|
|
8
|
-
description: `End-to-end reachability probe:
|
|
9
|
-
- Confirms the Graph API is reachable.
|
|
10
|
-
- Confirms the configured token resolves to a valid identity (via /me).
|
|
11
|
-
- Surfaces the latest rate-limit header snapshot from the Graph client.
|
|
12
|
-
- Lists which allowlists are active (business / ad account / page / IG user).
|
|
13
|
-
|
|
8
|
+
description: `End-to-end reachability probe:
|
|
9
|
+
- Confirms the Graph API is reachable.
|
|
10
|
+
- Confirms the configured token resolves to a valid identity (via /me).
|
|
11
|
+
- Surfaces the latest rate-limit header snapshot from the Graph client.
|
|
12
|
+
- Lists which allowlists are active (business / ad account / page / IG user).
|
|
13
|
+
|
|
14
14
|
Use when a session starts, or when diagnosing why other tools are returning errors.`,
|
|
15
15
|
inputSchema: inputSchema.shape,
|
|
16
16
|
annotations: {
|
|
@@ -34,6 +34,8 @@ export async function handler(_input, ctx) {
|
|
|
34
34
|
identity: me,
|
|
35
35
|
api_version: ctx.config.apiVersion,
|
|
36
36
|
appsecret_proof_enabled: Boolean(ctx.config.appSecret),
|
|
37
|
+
insights_app_configured: Boolean(ctx.config.insightsAccessToken),
|
|
38
|
+
insights_app_appsecret_proof_enabled: Boolean(ctx.config.insightsAppSecret),
|
|
37
39
|
rate_limit: ctx.graph.rateLimit,
|
|
38
40
|
allowlists: {
|
|
39
41
|
businesses: ctx.config.allowedBusinessIds ? [...ctx.config.allowedBusinessIds] : null,
|
|
@@ -10,17 +10,17 @@ export const inputSchema = z
|
|
|
10
10
|
export const definition = {
|
|
11
11
|
name: "meta_token_inspect",
|
|
12
12
|
title: "Inspect Meta access token",
|
|
13
|
-
description: `Decodes the configured META_ACCESS_TOKEN via Graph API /debug_token.
|
|
14
|
-
|
|
15
|
-
Returns:
|
|
16
|
-
- app_id + application name
|
|
17
|
-
- token type (system-user / user / page)
|
|
18
|
-
- is_valid
|
|
19
|
-
- expires_at + data_access_expires_at (unix seconds; 0 = never expires)
|
|
20
|
-
- scopes + granular_scopes (per-asset targeting)
|
|
21
|
-
|
|
22
|
-
Use this first when troubleshooting — almost every other tool failure traces back to a missing scope or an asset not assigned to the token.
|
|
23
|
-
|
|
13
|
+
description: `Decodes the configured META_ACCESS_TOKEN via Graph API /debug_token.
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
- app_id + application name
|
|
17
|
+
- token type (system-user / user / page)
|
|
18
|
+
- is_valid
|
|
19
|
+
- expires_at + data_access_expires_at (unix seconds; 0 = never expires)
|
|
20
|
+
- scopes + granular_scopes (per-asset targeting)
|
|
21
|
+
|
|
22
|
+
Use this first when troubleshooting — almost every other tool failure traces back to a missing scope or an asset not assigned to the token.
|
|
23
|
+
|
|
24
24
|
Never logs the token itself.`,
|
|
25
25
|
inputSchema: inputSchema.shape,
|
|
26
26
|
annotations: {
|
|
@@ -30,8 +30,8 @@ export const inputSchema = z
|
|
|
30
30
|
export const definition = {
|
|
31
31
|
name: "meta_whatsapp_get_analytics",
|
|
32
32
|
title: "Get WhatsApp Business analytics",
|
|
33
|
-
description: `Fetches WABA analytics — either the legacy 'analytics' field (message counts) or the richer 'conversation_analytics' (per-conversation pricing, categories: AUTHENTICATION/MARKETING/SERVICE/UTILITY).
|
|
34
|
-
|
|
33
|
+
description: `Fetches WABA analytics — either the legacy 'analytics' field (message counts) or the richer 'conversation_analytics' (per-conversation pricing, categories: AUTHENTICATION/MARKETING/SERVICE/UTILITY).
|
|
34
|
+
|
|
35
35
|
Pass start + end as Unix seconds. Use granularity DAY for most reports. Filter by phone_numbers, country_codes, or conversation_categories to narrow.`,
|
|
36
36
|
inputSchema: inputSchema.shape,
|
|
37
37
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
package/package.json
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@praise25/meta-mcp-server",
|
|
3
|
-
"description": "Read-only Model Context Protocol server for Meta Business Manager — Pages, Instagram, Ads insights, Pixels, Catalog, WhatsApp.",
|
|
4
|
-
"version": "0.1.
|
|
5
|
-
"author": "Stephen A.",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"homepage": "https://github.com/feladeveloper/meta-mcp-server#readme",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/feladeveloper/meta-mcp-server.git"
|
|
11
|
-
},
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/feladeveloper/meta-mcp-server/issues"
|
|
14
|
-
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
"mcp",
|
|
17
|
-
"model-context-protocol",
|
|
18
|
-
"meta",
|
|
19
|
-
"facebook",
|
|
20
|
-
"instagram",
|
|
21
|
-
"marketing-api",
|
|
22
|
-
"ads",
|
|
23
|
-
"ads-insights",
|
|
24
|
-
"pixels",
|
|
25
|
-
"catalog",
|
|
26
|
-
"whatsapp",
|
|
27
|
-
"business-manager",
|
|
28
|
-
"read-only",
|
|
29
|
-
"ai-tools",
|
|
30
|
-
"claude"
|
|
31
|
-
],
|
|
32
|
-
"type": "module",
|
|
33
|
-
"main": "dist/index.js",
|
|
34
|
-
"bin": {
|
|
35
|
-
"meta-business-manager-mcp-server": "dist/index.js"
|
|
36
|
-
},
|
|
37
|
-
"files": [
|
|
38
|
-
"dist",
|
|
39
|
-
"README.md",
|
|
40
|
-
"LICENSE"
|
|
41
|
-
],
|
|
42
|
-
"engines": {
|
|
43
|
-
"node": ">=20.10.0"
|
|
44
|
-
},
|
|
45
|
-
"scripts": {
|
|
46
|
-
"build:clean": "rm -rf dist",
|
|
47
|
-
"build:compile": "tsc --project tsconfig.build.json",
|
|
48
|
-
"build:chmod": "chmod +x dist/index.js || true",
|
|
49
|
-
"build": "npm run build:clean && npm run build:compile && npm run build:chmod",
|
|
50
|
-
"start": "node dist/index.js",
|
|
51
|
-
"dev": "tsx src/index.ts",
|
|
52
|
-
"inspect": "npm run build && npx @modelcontextprotocol/inspector dist/index.js",
|
|
53
|
-
"check:types": "tsc --noEmit --project tsconfig.json",
|
|
54
|
-
"test:readonly": "npm run build && node tests/read-only-guard.mjs",
|
|
55
|
-
"test:placeholder": "npm run build && node tests/placeholder-rejection.mjs",
|
|
56
|
-
"test:invariants": "npm run test:readonly && npm run test:placeholder",
|
|
57
|
-
"test:scenarios": "npm run build && node tests/scenarios.mjs",
|
|
58
|
-
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
59
|
-
"prepublishOnly": "npm run check:types && npm run test:invariants"
|
|
60
|
-
},
|
|
61
|
-
"dependencies": {
|
|
62
|
-
"@modelcontextprotocol/sdk": "^1.11.2",
|
|
63
|
-
"axios": "^1.7.7",
|
|
64
|
-
"lru-cache": "^11.1.0",
|
|
65
|
-
"pino": "^9.5.0",
|
|
66
|
-
"zod": "^3.23.8"
|
|
67
|
-
},
|
|
68
|
-
"devDependencies": {
|
|
69
|
-
"@jest/globals": "^30.0.0",
|
|
70
|
-
"@types/jest": "^30.0.0",
|
|
71
|
-
"@types/node": "^22.0.0",
|
|
72
|
-
"jest": "^30.0.0",
|
|
73
|
-
"ts-jest": "^29.2.0",
|
|
74
|
-
"tsx": "^4.19.0",
|
|
75
|
-
"typescript": "^5.6.0"
|
|
76
|
-
}
|
|
77
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@praise25/meta-mcp-server",
|
|
3
|
+
"description": "Read-only Model Context Protocol server for Meta Business Manager — Pages, Instagram, Ads insights, Pixels, Catalog, WhatsApp.",
|
|
4
|
+
"version": "0.1.11",
|
|
5
|
+
"author": "Stephen A.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/feladeveloper/meta-mcp-server#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/feladeveloper/meta-mcp-server.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/feladeveloper/meta-mcp-server/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"meta",
|
|
19
|
+
"facebook",
|
|
20
|
+
"instagram",
|
|
21
|
+
"marketing-api",
|
|
22
|
+
"ads",
|
|
23
|
+
"ads-insights",
|
|
24
|
+
"pixels",
|
|
25
|
+
"catalog",
|
|
26
|
+
"whatsapp",
|
|
27
|
+
"business-manager",
|
|
28
|
+
"read-only",
|
|
29
|
+
"ai-tools",
|
|
30
|
+
"claude"
|
|
31
|
+
],
|
|
32
|
+
"type": "module",
|
|
33
|
+
"main": "dist/index.js",
|
|
34
|
+
"bin": {
|
|
35
|
+
"meta-business-manager-mcp-server": "dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE"
|
|
41
|
+
],
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20.10.0"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build:clean": "rm -rf dist",
|
|
47
|
+
"build:compile": "tsc --project tsconfig.build.json",
|
|
48
|
+
"build:chmod": "chmod +x dist/index.js || true",
|
|
49
|
+
"build": "npm run build:clean && npm run build:compile && npm run build:chmod",
|
|
50
|
+
"start": "node dist/index.js",
|
|
51
|
+
"dev": "tsx src/index.ts",
|
|
52
|
+
"inspect": "npm run build && npx @modelcontextprotocol/inspector dist/index.js",
|
|
53
|
+
"check:types": "tsc --noEmit --project tsconfig.json",
|
|
54
|
+
"test:readonly": "npm run build && node tests/read-only-guard.mjs",
|
|
55
|
+
"test:placeholder": "npm run build && node tests/placeholder-rejection.mjs",
|
|
56
|
+
"test:invariants": "npm run test:readonly && npm run test:placeholder",
|
|
57
|
+
"test:scenarios": "npm run build && node tests/scenarios.mjs",
|
|
58
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
59
|
+
"prepublishOnly": "npm run check:types && npm run test:invariants"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"@modelcontextprotocol/sdk": "^1.11.2",
|
|
63
|
+
"axios": "^1.7.7",
|
|
64
|
+
"lru-cache": "^11.1.0",
|
|
65
|
+
"pino": "^9.5.0",
|
|
66
|
+
"zod": "^3.23.8"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@jest/globals": "^30.0.0",
|
|
70
|
+
"@types/jest": "^30.0.0",
|
|
71
|
+
"@types/node": "^22.0.0",
|
|
72
|
+
"jest": "^30.0.0",
|
|
73
|
+
"ts-jest": "^29.2.0",
|
|
74
|
+
"tsx": "^4.19.0",
|
|
75
|
+
"typescript": "^5.6.0"
|
|
76
|
+
}
|
|
77
|
+
}
|