@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.
Files changed (37) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +292 -292
  3. package/dist/config.d.ts +24 -0
  4. package/dist/config.js +14 -0
  5. package/dist/constants.d.ts +1 -1
  6. package/dist/constants.js +1 -1
  7. package/dist/helpers/graph-client.d.ts +11 -1
  8. package/dist/helpers/graph-client.js +24 -16
  9. package/dist/index.js +0 -0
  10. package/dist/server.js +21 -1
  11. package/dist/tools/ads/get-insights.d.ts +1 -1
  12. package/dist/tools/ads/get-insights.js +12 -10
  13. package/dist/tools/ads/list-accounts.js +4 -4
  14. package/dist/tools/business/list-assets.js +10 -10
  15. package/dist/tools/business/list-businesses.js +4 -4
  16. package/dist/tools/business/list-system-users.js +4 -4
  17. package/dist/tools/instagram/get-audience-demographics.d.ts +5 -1
  18. package/dist/tools/instagram/get-audience-demographics.js +17 -10
  19. package/dist/tools/instagram/get-media-insights.js +14 -14
  20. package/dist/tools/instagram/list-accounts.js +2 -2
  21. package/dist/tools/meta/graph-read.js +7 -7
  22. package/dist/tools/overview/business-overview.js +10 -10
  23. package/dist/tools/overview/content-report.d.ts +57 -0
  24. package/dist/tools/overview/content-report.js +344 -0
  25. package/dist/tools/overview/latest-posts-summary.d.ts +1 -1
  26. package/dist/tools/overview/latest-posts-summary.js +10 -16
  27. package/dist/tools/pages/get-insights.js +2 -2
  28. package/dist/tools/pages/get-post-insights.js +4 -4
  29. package/dist/tools/pages/list-posts.d.ts +1 -1
  30. package/dist/tools/pages/list-posts.js +3 -1
  31. package/dist/tools/register.js +3 -2
  32. package/dist/tools/shared.d.ts +19 -4
  33. package/dist/tools/shared.js +56 -0
  34. package/dist/tools/token/health.js +8 -6
  35. package/dist/tools/token/inspect.js +11 -11
  36. package/dist/tools/whatsapp/get-analytics.js +2 -2
  37. package/package.json +77 -77
@@ -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.8",
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
+ }