@praise25/meta-mcp-server 0.1.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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +292 -0
  3. package/dist/config.d.ts +15 -0
  4. package/dist/config.js +46 -0
  5. package/dist/constants.d.ts +21 -0
  6. package/dist/constants.js +28 -0
  7. package/dist/context.d.ts +9 -0
  8. package/dist/context.js +8 -0
  9. package/dist/errors.d.ts +41 -0
  10. package/dist/errors.js +90 -0
  11. package/dist/helpers/cache.d.ts +6 -0
  12. package/dist/helpers/cache.js +28 -0
  13. package/dist/helpers/format.d.ts +17 -0
  14. package/dist/helpers/format.js +28 -0
  15. package/dist/helpers/graph-client.d.ts +56 -0
  16. package/dist/helpers/graph-client.js +169 -0
  17. package/dist/helpers/schema.d.ts +30 -0
  18. package/dist/helpers/schema.js +69 -0
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.js +36 -0
  21. package/dist/logger.d.ts +3 -0
  22. package/dist/logger.js +18 -0
  23. package/dist/server.d.ts +7 -0
  24. package/dist/server.js +14 -0
  25. package/dist/tools/ads/get-account.d.ts +29 -0
  26. package/dist/tools/ads/get-account.js +45 -0
  27. package/dist/tools/ads/get-creative.d.ts +29 -0
  28. package/dist/tools/ads/get-creative.js +37 -0
  29. package/dist/tools/ads/get-insights.d.ts +129 -0
  30. package/dist/tools/ads/get-insights.js +151 -0
  31. package/dist/tools/ads/list-accounts.d.ts +54 -0
  32. package/dist/tools/ads/list-accounts.js +59 -0
  33. package/dist/tools/ads/list-ads.d.ts +53 -0
  34. package/dist/tools/ads/list-ads.js +59 -0
  35. package/dist/tools/ads/list-adsets.d.ts +49 -0
  36. package/dist/tools/ads/list-adsets.js +54 -0
  37. package/dist/tools/ads/list-campaigns.d.ts +45 -0
  38. package/dist/tools/ads/list-campaigns.js +64 -0
  39. package/dist/tools/ads/list-custom-audiences.d.ts +41 -0
  40. package/dist/tools/ads/list-custom-audiences.js +41 -0
  41. package/dist/tools/business/list-assets.d.ts +37 -0
  42. package/dist/tools/business/list-assets.js +136 -0
  43. package/dist/tools/business/list-businesses.d.ts +37 -0
  44. package/dist/tools/business/list-businesses.js +81 -0
  45. package/dist/tools/business/list-system-users.d.ts +41 -0
  46. package/dist/tools/business/list-system-users.js +73 -0
  47. package/dist/tools/catalog/get-diagnostics.d.ts +29 -0
  48. package/dist/tools/catalog/get-diagnostics.js +26 -0
  49. package/dist/tools/catalog/list-products.d.ts +45 -0
  50. package/dist/tools/catalog/list-products.js +49 -0
  51. package/dist/tools/catalog/list.d.ts +54 -0
  52. package/dist/tools/catalog/list.js +48 -0
  53. package/dist/tools/instagram/get-account.d.ts +29 -0
  54. package/dist/tools/instagram/get-account.js +34 -0
  55. package/dist/tools/instagram/get-audience-demographics.d.ts +41 -0
  56. package/dist/tools/instagram/get-audience-demographics.js +46 -0
  57. package/dist/tools/instagram/get-media-insights.d.ts +29 -0
  58. package/dist/tools/instagram/get-media-insights.js +43 -0
  59. package/dist/tools/instagram/list-accounts.d.ts +33 -0
  60. package/dist/tools/instagram/list-accounts.js +63 -0
  61. package/dist/tools/instagram/list-media.d.ts +41 -0
  62. package/dist/tools/instagram/list-media.js +42 -0
  63. package/dist/tools/meta/graph-read.d.ts +33 -0
  64. package/dist/tools/meta/graph-read.js +71 -0
  65. package/dist/tools/overview/business-overview.d.ts +49 -0
  66. package/dist/tools/overview/business-overview.js +188 -0
  67. package/dist/tools/pages/get-insights.d.ts +41 -0
  68. package/dist/tools/pages/get-insights.js +49 -0
  69. package/dist/tools/pages/get-post-insights.d.ts +29 -0
  70. package/dist/tools/pages/get-post-insights.js +36 -0
  71. package/dist/tools/pages/get.d.ts +29 -0
  72. package/dist/tools/pages/get.js +50 -0
  73. package/dist/tools/pages/list-posts.d.ts +53 -0
  74. package/dist/tools/pages/list-posts.js +54 -0
  75. package/dist/tools/pages/list-reviews.d.ts +41 -0
  76. package/dist/tools/pages/list-reviews.js +37 -0
  77. package/dist/tools/pages/list-videos.d.ts +41 -0
  78. package/dist/tools/pages/list-videos.js +40 -0
  79. package/dist/tools/pages/list.d.ts +41 -0
  80. package/dist/tools/pages/list.js +39 -0
  81. package/dist/tools/pixels/get-stats.d.ts +41 -0
  82. package/dist/tools/pixels/get-stats.js +34 -0
  83. package/dist/tools/pixels/list.d.ts +41 -0
  84. package/dist/tools/pixels/list.js +38 -0
  85. package/dist/tools/register.d.ts +3 -0
  86. package/dist/tools/register.js +82 -0
  87. package/dist/tools/shared.d.ts +20 -0
  88. package/dist/tools/shared.js +55 -0
  89. package/dist/tools/token/health.d.ts +17 -0
  90. package/dist/tools/token/health.js +59 -0
  91. package/dist/tools/token/inspect.d.ts +26 -0
  92. package/dist/tools/token/inspect.js +88 -0
  93. package/dist/tools/whatsapp/get-analytics.d.ts +57 -0
  94. package/dist/tools/whatsapp/get-analytics.js +66 -0
  95. package/dist/tools/whatsapp/list-phone-numbers.d.ts +41 -0
  96. package/dist/tools/whatsapp/list-phone-numbers.js +35 -0
  97. package/dist/tools/whatsapp/list-templates.d.ts +45 -0
  98. package/dist/tools/whatsapp/list-templates.js +44 -0
  99. package/dist/tools/whatsapp/list-wabas.d.ts +54 -0
  100. package/dist/tools/whatsapp/list-wabas.js +48 -0
  101. package/dist/types/meta.d.ts +46 -0
  102. package/dist/types/meta.js +1 -0
  103. package/package.json +74 -0
@@ -0,0 +1,71 @@
1
+ import { z } from "zod";
2
+ import { MetaError } from "../../errors.js";
3
+ import { jsonBlock, toolError, toolResult } from "../../helpers/format.js";
4
+ const paramsRecord = z
5
+ .record(z.union([z.string(), z.number(), z.boolean()]))
6
+ .optional()
7
+ .describe("Query parameters. `access_token` and `appsecret_proof` are added automatically and must not be supplied here.");
8
+ export const inputSchema = z
9
+ .object({
10
+ path: z
11
+ .string()
12
+ .min(1)
13
+ .describe("Graph API path after the version segment. Examples: 'me/businesses', 'act_1234567890/insights', '100000012345/posts'. Do NOT include a leading 'v23.0/' — the configured API version is added automatically."),
14
+ params: paramsRecord,
15
+ api_version: z
16
+ .string()
17
+ .regex(/^v\d+\.\d+$/)
18
+ .optional()
19
+ .describe("Override the Graph API version for this call, e.g. 'v20.0'. Defaults to the configured version."),
20
+ })
21
+ .strict();
22
+ const FORBIDDEN_PARAMS = new Set(["access_token", "appsecret_proof"]);
23
+ export const definition = {
24
+ name: "meta_graph_read",
25
+ title: "Arbitrary read-only Graph API call",
26
+ description: `Escape-hatch for arbitrary GET requests against the Meta Graph API.
27
+
28
+ This tool exists so the assistant can reach fields and endpoints that do not yet have a dedicated tool wrapper — without ever sending a write. The underlying HTTP client is hard-wired to GET only; POST/PUT/DELETE are refused before the request leaves the process.
29
+
30
+ Rules:
31
+ - Do NOT include 'access_token' or 'appsecret_proof' in params — they are added automatically.
32
+ - Do NOT prefix the path with the API version.
33
+ - Prefer dedicated tools (meta_business_list_assets, meta_ads_get_insights, …) when they exist. Use this as a last resort.`,
34
+ inputSchema: inputSchema.shape,
35
+ annotations: {
36
+ readOnlyHint: true,
37
+ destructiveHint: false,
38
+ idempotentHint: true,
39
+ openWorldHint: true,
40
+ },
41
+ };
42
+ export async function handler(input, ctx) {
43
+ for (const k of Object.keys(input.params ?? {})) {
44
+ if (FORBIDDEN_PARAMS.has(k)) {
45
+ return toolError(`Parameter '${k}' must not be supplied — the server adds it automatically.`, "Remove it from the params object and retry.");
46
+ }
47
+ }
48
+ try {
49
+ const data = await ctx.graph.get({
50
+ path: input.path,
51
+ params: input.params,
52
+ apiVersion: input.api_version,
53
+ });
54
+ const structured = {
55
+ path: input.path,
56
+ api_version: input.api_version ?? ctx.config.apiVersion,
57
+ data,
58
+ };
59
+ return toolResult(structured, jsonBlock(data));
60
+ }
61
+ catch (err) {
62
+ const e = err instanceof MetaError ? err : new MetaError(err.message);
63
+ return toolError(e.message, e.hint, {
64
+ code: e.code,
65
+ subcode: e.subcode,
66
+ fbtrace_id: e.fbtraceId,
67
+ http_status: e.httpStatus,
68
+ path: input.path,
69
+ });
70
+ }
71
+ }
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ import type { ToolContext } from "../../context.js";
3
+ export declare const inputSchema: z.ZodObject<{
4
+ business_id: z.ZodString;
5
+ date_preset: z.ZodDefault<z.ZodEnum<["today", "yesterday", "this_month", "last_month", "this_quarter", "maximum", "last_3d", "last_7d", "last_14d", "last_28d", "last_30d", "last_90d", "last_week_mon_sun", "last_week_sun_sat", "last_quarter", "last_year", "this_week_mon_today", "this_week_sun_today", "this_year"]>>;
6
+ include_pixels: z.ZodDefault<z.ZodBoolean>;
7
+ include_catalogs: z.ZodDefault<z.ZodBoolean>;
8
+ include_whatsapp: z.ZodDefault<z.ZodBoolean>;
9
+ max_ad_accounts: z.ZodDefault<z.ZodNumber>;
10
+ max_pages: z.ZodDefault<z.ZodNumber>;
11
+ }, "strict", z.ZodTypeAny, {
12
+ business_id: string;
13
+ date_preset: "today" | "yesterday" | "this_month" | "last_month" | "this_quarter" | "maximum" | "last_3d" | "last_7d" | "last_14d" | "last_28d" | "last_30d" | "last_90d" | "last_week_mon_sun" | "last_week_sun_sat" | "last_quarter" | "last_year" | "this_week_mon_today" | "this_week_sun_today" | "this_year";
14
+ include_pixels: boolean;
15
+ include_catalogs: boolean;
16
+ include_whatsapp: boolean;
17
+ max_ad_accounts: number;
18
+ max_pages: number;
19
+ }, {
20
+ business_id: string;
21
+ date_preset?: "today" | "yesterday" | "this_month" | "last_month" | "this_quarter" | "maximum" | "last_3d" | "last_7d" | "last_14d" | "last_28d" | "last_30d" | "last_90d" | "last_week_mon_sun" | "last_week_sun_sat" | "last_quarter" | "last_year" | "this_week_mon_today" | "this_week_sun_today" | "this_year" | undefined;
22
+ include_pixels?: boolean | undefined;
23
+ include_catalogs?: boolean | undefined;
24
+ include_whatsapp?: boolean | undefined;
25
+ max_ad_accounts?: number | undefined;
26
+ max_pages?: number | undefined;
27
+ }>;
28
+ export type Input = z.infer<typeof inputSchema>;
29
+ export declare const definition: {
30
+ readonly name: "meta_business_overview";
31
+ readonly title: "Eagle's-eye snapshot of a business";
32
+ readonly description: "One-call consolidated read across the whole Meta surface for a business:\n\n- Identity (system user + token app)\n- Assigned Pages + each Page's high-level insights (impressions, engagement, fans) for the requested window\n- Instagram Business accounts linked to those Pages (followers, media_count)\n- Owned + client ad accounts with balance, spend cap, amount spent, and last-window insights (spend, impressions, clicks, CTR, CPC, reach)\n- Pixels with last_fired_time (if include_pixels)\n- Catalogs with product counts (if include_catalogs)\n- WhatsApp Business Accounts + phone numbers (if include_whatsapp)\n\nEach section has its own error isolation — one failing asset does not kill the report. Ideal as the opening call for any AI-driven marketing insights conversation.";
33
+ readonly inputSchema: {
34
+ business_id: z.ZodString;
35
+ date_preset: z.ZodDefault<z.ZodEnum<["today", "yesterday", "this_month", "last_month", "this_quarter", "maximum", "last_3d", "last_7d", "last_14d", "last_28d", "last_30d", "last_90d", "last_week_mon_sun", "last_week_sun_sat", "last_quarter", "last_year", "this_week_mon_today", "this_week_sun_today", "this_year"]>>;
36
+ include_pixels: z.ZodDefault<z.ZodBoolean>;
37
+ include_catalogs: z.ZodDefault<z.ZodBoolean>;
38
+ include_whatsapp: z.ZodDefault<z.ZodBoolean>;
39
+ max_ad_accounts: z.ZodDefault<z.ZodNumber>;
40
+ max_pages: z.ZodDefault<z.ZodNumber>;
41
+ };
42
+ readonly annotations: {
43
+ readonly readOnlyHint: true;
44
+ readonly destructiveHint: false;
45
+ readonly idempotentHint: true;
46
+ readonly openWorldHint: true;
47
+ };
48
+ };
49
+ export declare function handler(input: Input, ctx: ToolContext): Promise<import("../../helpers/format.js").ToolTextResult>;
@@ -0,0 +1,188 @@
1
+ import { z } from "zod";
2
+ import { assertAllowed } from "../../config.js";
3
+ import { MetaError } from "../../errors.js";
4
+ import { jsonBlock, toolResult } from "../../helpers/format.js";
5
+ import { datePresetSchema, metaIdSchema } from "../../helpers/schema.js";
6
+ export const inputSchema = z
7
+ .object({
8
+ business_id: metaIdSchema.describe("Business Manager ID."),
9
+ date_preset: datePresetSchema
10
+ .default("last_30d")
11
+ .describe("Date window used for ad account and page insights snapshots."),
12
+ include_pixels: z.boolean().default(true),
13
+ include_catalogs: z.boolean().default(true),
14
+ include_whatsapp: z.boolean().default(true),
15
+ max_ad_accounts: z.number().int().min(1).max(50).default(10).describe("Cap on number of ad accounts to fetch insights for. Each is one extra Graph call — tune for rate limits."),
16
+ max_pages: z.number().int().min(1).max(50).default(10).describe("Cap on number of Pages to fetch insights for."),
17
+ })
18
+ .strict();
19
+ export const definition = {
20
+ name: "meta_business_overview",
21
+ title: "Eagle's-eye snapshot of a business",
22
+ description: `One-call consolidated read across the whole Meta surface for a business:
23
+
24
+ - Identity (system user + token app)
25
+ - Assigned Pages + each Page's high-level insights (impressions, engagement, fans) for the requested window
26
+ - Instagram Business accounts linked to those Pages (followers, media_count)
27
+ - Owned + client ad accounts with balance, spend cap, amount spent, and last-window insights (spend, impressions, clicks, CTR, CPC, reach)
28
+ - Pixels with last_fired_time (if include_pixels)
29
+ - Catalogs with product counts (if include_catalogs)
30
+ - WhatsApp Business Accounts + phone numbers (if include_whatsapp)
31
+
32
+ Each section has its own error isolation — one failing asset does not kill the report. Ideal as the opening call for any AI-driven marketing insights conversation.`,
33
+ inputSchema: inputSchema.shape,
34
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
35
+ };
36
+ function ok(data) {
37
+ return { ok: true, data };
38
+ }
39
+ function fail(err) {
40
+ const e = err instanceof MetaError ? err : new MetaError(err.message);
41
+ return { ok: false, error: e.message, hint: e.hint };
42
+ }
43
+ export async function handler(input, ctx) {
44
+ assertAllowed("business", input.business_id, ctx.config);
45
+ const started = Date.now();
46
+ const token = ctx.graph.get({
47
+ path: "debug_token",
48
+ params: { input_token: ctx.config.accessToken },
49
+ noCache: true,
50
+ }).then((r) => ok(r.data)).catch(fail);
51
+ const identity = ctx.graph.get({ path: "me", params: { fields: "id,name" } })
52
+ .then(ok)
53
+ .catch(fail);
54
+ const pages = ctx.graph
55
+ .get({
56
+ path: "me/assigned_pages",
57
+ params: { fields: "id,name,category,fan_count,followers_count", limit: input.max_pages },
58
+ })
59
+ .then(ok)
60
+ .catch(fail);
61
+ const ownedAds = ctx.graph
62
+ .get({
63
+ path: `${input.business_id}/owned_ad_accounts`,
64
+ params: { fields: "id,account_id,name,currency,account_status,amount_spent,balance,spend_cap", limit: input.max_ad_accounts },
65
+ })
66
+ .then(ok)
67
+ .catch(fail);
68
+ const clientAds = ctx.graph
69
+ .get({
70
+ path: `${input.business_id}/client_ad_accounts`,
71
+ params: { fields: "id,account_id,name,currency,account_status", limit: input.max_ad_accounts },
72
+ })
73
+ .then(ok)
74
+ .catch(fail);
75
+ const pixels = input.include_pixels
76
+ ? ctx.graph
77
+ .get({
78
+ path: `${input.business_id}/owned_pixels`,
79
+ params: { fields: "id,name,last_fired_time,is_unavailable", limit: 25 },
80
+ })
81
+ .then(ok)
82
+ .catch(fail)
83
+ : Promise.resolve(ok({ skipped: true }));
84
+ const catalogs = input.include_catalogs
85
+ ? ctx.graph
86
+ .get({
87
+ path: `${input.business_id}/owned_product_catalogs`,
88
+ params: { fields: "id,name,vertical,product_count", limit: 25 },
89
+ })
90
+ .then(ok)
91
+ .catch(fail)
92
+ : Promise.resolve(ok({ skipped: true }));
93
+ const wabas = input.include_whatsapp
94
+ ? ctx.graph
95
+ .get({
96
+ path: `${input.business_id}/owned_whatsapp_business_accounts`,
97
+ params: { fields: "id,name,currency,status,business_verification_status", limit: 25 },
98
+ })
99
+ .then(ok)
100
+ .catch(fail)
101
+ : Promise.resolve(ok({ skipped: true }));
102
+ const [identityR, tokenR, pagesR, ownedAdsR, clientAdsR, pixelsR, catalogsR, wabasR] = await Promise.all([
103
+ identity,
104
+ token,
105
+ pages,
106
+ ownedAds,
107
+ clientAds,
108
+ pixels,
109
+ catalogs,
110
+ wabas,
111
+ ]);
112
+ // Expand each page with linked IG + a small insights fetch.
113
+ const pagesExpanded = pagesR.ok && pagesR.data.data
114
+ ? await Promise.all(pagesR.data.data.map(async (p) => {
115
+ const [igR, insightsR] = await Promise.all([
116
+ ctx.graph
117
+ .get({
118
+ path: p.id,
119
+ params: { fields: "instagram_business_account{id,username,name,followers_count,media_count}" },
120
+ })
121
+ .then(ok)
122
+ .catch(fail),
123
+ ctx.graph
124
+ .get({
125
+ path: `${p.id}/insights`,
126
+ params: {
127
+ // Narrow v23-safe metric set; requires 'read_insights' scope.
128
+ metric: "page_impressions,page_post_engagements,page_fans,page_views_total",
129
+ date_preset: input.date_preset,
130
+ },
131
+ })
132
+ .then(ok)
133
+ .catch(fail),
134
+ ]);
135
+ return {
136
+ id: p.id,
137
+ name: p.name,
138
+ category: p.category,
139
+ fan_count: p.fan_count,
140
+ followers_count: p.followers_count,
141
+ instagram: igR.ok ? igR.data.instagram_business_account ?? null : { error: igR.error, hint: igR.hint },
142
+ insights_last_window: insightsR.ok ? insightsR.data.data ?? [] : { error: insightsR.error, hint: insightsR.hint },
143
+ };
144
+ }))
145
+ : [];
146
+ // Same treatment for ad accounts.
147
+ const adAccountsData = [
148
+ ...((ownedAdsR.ok && ownedAdsR.data.data) ? ownedAdsR.data.data.map((a) => ({ ...a, scope: "owned" })) : []),
149
+ ...((clientAdsR.ok && clientAdsR.data.data) ? clientAdsR.data.data.map((a) => ({ ...a, scope: "client" })) : []),
150
+ ].slice(0, input.max_ad_accounts);
151
+ const adAccountsExpanded = await Promise.all(adAccountsData.map(async (a) => {
152
+ const insightsR = await ctx.graph
153
+ .get({
154
+ path: `${a.id}/insights`,
155
+ params: {
156
+ level: "account",
157
+ fields: "spend,impressions,reach,frequency,clicks,ctr,cpc,cpm,actions",
158
+ date_preset: input.date_preset,
159
+ },
160
+ })
161
+ .then(ok)
162
+ .catch(fail);
163
+ return {
164
+ id: a.id,
165
+ account_id: a.account_id,
166
+ name: a.name,
167
+ scope: a.scope,
168
+ currency: a.currency,
169
+ account_status: a.account_status,
170
+ insights_last_window: insightsR.ok ? insightsR.data.data?.[0] ?? null : { error: insightsR.error, hint: insightsR.hint },
171
+ };
172
+ }));
173
+ const structured = {
174
+ business_id: input.business_id,
175
+ date_preset: input.date_preset,
176
+ generated_at: new Date().toISOString(),
177
+ latency_ms: Date.now() - started,
178
+ identity: identityR,
179
+ token: tokenR,
180
+ pages: pagesExpanded,
181
+ ad_accounts: adAccountsExpanded,
182
+ pixels: pixelsR,
183
+ catalogs: catalogsR,
184
+ whatsapp: wabasR,
185
+ rate_limit_after: ctx.graph.rateLimit,
186
+ };
187
+ return toolResult(structured, jsonBlock(structured));
188
+ }
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ import type { ToolContext } from "../../context.js";
3
+ export declare const inputSchema: z.ZodObject<{
4
+ page_id: z.ZodString;
5
+ metrics: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
6
+ period: z.ZodDefault<z.ZodEnum<["day", "week", "days_28", "lifetime", "total_over_range"]>>;
7
+ since: z.ZodOptional<z.ZodString>;
8
+ until: z.ZodOptional<z.ZodString>;
9
+ }, "strict", z.ZodTypeAny, {
10
+ page_id: string;
11
+ metrics: string[];
12
+ period: "day" | "week" | "days_28" | "lifetime" | "total_over_range";
13
+ since?: string | undefined;
14
+ until?: string | undefined;
15
+ }, {
16
+ page_id: string;
17
+ since?: string | undefined;
18
+ until?: string | undefined;
19
+ metrics?: string[] | undefined;
20
+ period?: "day" | "week" | "days_28" | "lifetime" | "total_over_range" | undefined;
21
+ }>;
22
+ export type Input = z.infer<typeof inputSchema>;
23
+ export declare const definition: {
24
+ readonly name: "meta_page_get_insights";
25
+ readonly title: "Get Page-level insights";
26
+ readonly description: "Reads Page-level metrics: impressions, reach, engagements, fan growth, page views, video views. Requires 'read_insights' scope. Pick the right period per metric — many accept only 'day' or 'days_28'.";
27
+ readonly inputSchema: {
28
+ page_id: z.ZodString;
29
+ metrics: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
30
+ period: z.ZodDefault<z.ZodEnum<["day", "week", "days_28", "lifetime", "total_over_range"]>>;
31
+ since: z.ZodOptional<z.ZodString>;
32
+ until: z.ZodOptional<z.ZodString>;
33
+ };
34
+ readonly annotations: {
35
+ readonly readOnlyHint: true;
36
+ readonly destructiveHint: false;
37
+ readonly idempotentHint: true;
38
+ readonly openWorldHint: true;
39
+ };
40
+ };
41
+ export declare function handler(input: Input, ctx: ToolContext): Promise<import("../../helpers/format.js").ToolTextResult>;
@@ -0,0 +1,49 @@
1
+ import { z } from "zod";
2
+ import { assertAllowed } from "../../config.js";
3
+ import { metaIdSchema } from "../../helpers/schema.js";
4
+ import { runGet } from "../shared.js";
5
+ const PERIOD = z.enum(["day", "week", "days_28", "lifetime", "total_over_range"]);
6
+ export const inputSchema = z
7
+ .object({
8
+ page_id: metaIdSchema,
9
+ metrics: z
10
+ .array(z.string())
11
+ .default([
12
+ // Metrics that Meta still supports as of v23 (2026).
13
+ // Several 2023/2024 deprecations removed: page_consumptions, page_fan_removes,
14
+ // page_actions_post_reactions_total, page_impressions_organic (use unique/paid combo instead).
15
+ "page_impressions",
16
+ "page_impressions_unique",
17
+ "page_impressions_paid",
18
+ "page_post_engagements",
19
+ "page_fans",
20
+ "page_fan_adds",
21
+ "page_views_total",
22
+ "page_video_views",
23
+ "page_video_views_paid",
24
+ ])
25
+ .describe("Page insight metrics. Not every metric supports every period — see https://developers.facebook.com/docs/graph-api/reference/v23.0/insights. Requires 'read_insights' scope."),
26
+ period: PERIOD.default("day"),
27
+ since: z.string().optional().describe("ISO date or Unix timestamp."),
28
+ until: z.string().optional().describe("ISO date or Unix timestamp."),
29
+ })
30
+ .strict();
31
+ export const definition = {
32
+ name: "meta_page_get_insights",
33
+ title: "Get Page-level insights",
34
+ description: `Reads Page-level metrics: impressions, reach, engagements, fan growth, page views, video views. Requires 'read_insights' scope. Pick the right period per metric — many accept only 'day' or 'days_28'.`,
35
+ inputSchema: inputSchema.shape,
36
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
37
+ };
38
+ export async function handler(input, ctx) {
39
+ assertAllowed("page", input.page_id, ctx.config);
40
+ return runGet(ctx, {
41
+ path: `${input.page_id}/insights`,
42
+ params: {
43
+ metric: input.metrics.join(","),
44
+ period: input.period,
45
+ since: input.since,
46
+ until: input.until,
47
+ },
48
+ });
49
+ }
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ import type { ToolContext } from "../../context.js";
3
+ export declare const inputSchema: z.ZodObject<{
4
+ post_id: z.ZodString;
5
+ metrics: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
6
+ }, "strict", z.ZodTypeAny, {
7
+ post_id: string;
8
+ metrics: string[];
9
+ }, {
10
+ post_id: string;
11
+ metrics?: string[] | undefined;
12
+ }>;
13
+ export type Input = z.infer<typeof inputSchema>;
14
+ export declare const definition: {
15
+ readonly name: "meta_page_get_post_insights";
16
+ readonly title: "Get insights for a single Page post";
17
+ readonly description: "Reads impressions, unique reach, paid vs. organic split, engaged users, click counts, reactions-by-type, and video view metrics for a single post. Requires 'read_insights' scope.";
18
+ readonly inputSchema: {
19
+ post_id: z.ZodString;
20
+ metrics: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
21
+ };
22
+ readonly annotations: {
23
+ readonly readOnlyHint: true;
24
+ readonly destructiveHint: false;
25
+ readonly idempotentHint: true;
26
+ readonly openWorldHint: true;
27
+ };
28
+ };
29
+ export declare function handler(input: Input, ctx: ToolContext): Promise<import("../../helpers/format.js").ToolTextResult>;
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+ import { metaIdSchema } from "../../helpers/schema.js";
3
+ import { runGet } from "../shared.js";
4
+ export const inputSchema = z
5
+ .object({
6
+ post_id: metaIdSchema.describe("Post ID (format '{page_id}_{post_id}' or shortform)."),
7
+ metrics: z
8
+ .array(z.string())
9
+ .default([
10
+ "post_impressions",
11
+ "post_impressions_unique",
12
+ "post_impressions_paid",
13
+ "post_impressions_organic",
14
+ "post_engaged_users",
15
+ "post_clicks",
16
+ "post_reactions_by_type_total",
17
+ "post_video_views",
18
+ "post_video_views_unique",
19
+ "post_video_avg_time_watched",
20
+ ])
21
+ .describe("Post-level insight metrics. See https://developers.facebook.com/docs/graph-api/reference/v23.0/insights"),
22
+ })
23
+ .strict();
24
+ export const definition = {
25
+ name: "meta_page_get_post_insights",
26
+ title: "Get insights for a single Page post",
27
+ description: `Reads impressions, unique reach, paid vs. organic split, engaged users, click counts, reactions-by-type, and video view metrics for a single post. Requires 'read_insights' scope.`,
28
+ inputSchema: inputSchema.shape,
29
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
30
+ };
31
+ export async function handler(input, ctx) {
32
+ return runGet(ctx, {
33
+ path: `${input.post_id}/insights`,
34
+ params: { metric: input.metrics.join(",") },
35
+ });
36
+ }
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ import type { ToolContext } from "../../context.js";
3
+ export declare const inputSchema: z.ZodObject<{
4
+ page_id: z.ZodString;
5
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
6
+ }, "strict", z.ZodTypeAny, {
7
+ fields: string[];
8
+ page_id: string;
9
+ }, {
10
+ page_id: string;
11
+ fields?: string[] | undefined;
12
+ }>;
13
+ export type Input = z.infer<typeof inputSchema>;
14
+ export declare const definition: {
15
+ readonly name: "meta_page_get";
16
+ readonly title: "Get Page details";
17
+ readonly description: "Full page profile snapshot: category, about, fan count, rating, engagement, linked IG Business account, cover/picture. Use as the 'know-your-page' call before fetching posts or insights.";
18
+ readonly inputSchema: {
19
+ page_id: z.ZodString;
20
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
21
+ };
22
+ readonly annotations: {
23
+ readonly readOnlyHint: true;
24
+ readonly destructiveHint: false;
25
+ readonly idempotentHint: true;
26
+ readonly openWorldHint: true;
27
+ };
28
+ };
29
+ export declare function handler(input: Input, ctx: ToolContext): Promise<import("../../helpers/format.js").ToolTextResult>;
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import { assertAllowed } from "../../config.js";
3
+ import { metaIdSchema } from "../../helpers/schema.js";
4
+ import { runGet } from "../shared.js";
5
+ export const inputSchema = z
6
+ .object({
7
+ page_id: metaIdSchema,
8
+ fields: z
9
+ .array(z.string())
10
+ .default([
11
+ "id",
12
+ "name",
13
+ "username",
14
+ "category",
15
+ "category_list",
16
+ "about",
17
+ "description",
18
+ "fan_count",
19
+ "followers_count",
20
+ "verification_status",
21
+ "rating_count",
22
+ "overall_star_rating",
23
+ "link",
24
+ "website",
25
+ "phone",
26
+ "emails",
27
+ "location",
28
+ "single_line_address",
29
+ "engagement",
30
+ "talking_about_count",
31
+ "were_here_count",
32
+ "checkins",
33
+ "cover",
34
+ "picture.type(large)",
35
+ "instagram_business_account{id,username,name}",
36
+ ])
37
+ .describe("Page fields. Includes linked Instagram Business account when present."),
38
+ })
39
+ .strict();
40
+ export const definition = {
41
+ name: "meta_page_get",
42
+ title: "Get Page details",
43
+ description: `Full page profile snapshot: category, about, fan count, rating, engagement, linked IG Business account, cover/picture. Use as the 'know-your-page' call before fetching posts or insights.`,
44
+ inputSchema: inputSchema.shape,
45
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
46
+ };
47
+ export async function handler(input, ctx) {
48
+ assertAllowed("page", input.page_id, ctx.config);
49
+ return runGet(ctx, { path: input.page_id, params: { fields: input.fields.join(",") } });
50
+ }
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+ import type { ToolContext } from "../../context.js";
3
+ export declare const inputSchema: z.ZodObject<{
4
+ limit: z.ZodDefault<z.ZodNumber>;
5
+ after: z.ZodOptional<z.ZodString>;
6
+ auto_paginate: z.ZodDefault<z.ZodBoolean>;
7
+ page_id: z.ZodString;
8
+ edge: z.ZodDefault<z.ZodEnum<["posts", "published_posts", "feed"]>>;
9
+ since: z.ZodOptional<z.ZodString>;
10
+ until: z.ZodOptional<z.ZodString>;
11
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
12
+ }, "strict", z.ZodTypeAny, {
13
+ fields: string[];
14
+ limit: number;
15
+ auto_paginate: boolean;
16
+ edge: "posts" | "published_posts" | "feed";
17
+ page_id: string;
18
+ since?: string | undefined;
19
+ until?: string | undefined;
20
+ after?: string | undefined;
21
+ }, {
22
+ page_id: string;
23
+ since?: string | undefined;
24
+ until?: string | undefined;
25
+ fields?: string[] | undefined;
26
+ limit?: number | undefined;
27
+ after?: string | undefined;
28
+ auto_paginate?: boolean | undefined;
29
+ edge?: "posts" | "published_posts" | "feed" | undefined;
30
+ }>;
31
+ export type Input = z.infer<typeof inputSchema>;
32
+ export declare const definition: {
33
+ readonly name: "meta_page_list_posts";
34
+ readonly title: "List Page posts";
35
+ readonly description: "Lists Page posts with attached counts (reactions, comments, shares). Use since/until for a date window. The ID returned for each post is the one meta_page_get_post_insights expects.";
36
+ readonly inputSchema: {
37
+ limit: z.ZodDefault<z.ZodNumber>;
38
+ after: z.ZodOptional<z.ZodString>;
39
+ auto_paginate: z.ZodDefault<z.ZodBoolean>;
40
+ page_id: z.ZodString;
41
+ edge: z.ZodDefault<z.ZodEnum<["posts", "published_posts", "feed"]>>;
42
+ since: z.ZodOptional<z.ZodString>;
43
+ until: z.ZodOptional<z.ZodString>;
44
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
45
+ };
46
+ readonly annotations: {
47
+ readonly readOnlyHint: true;
48
+ readonly destructiveHint: false;
49
+ readonly idempotentHint: true;
50
+ readonly openWorldHint: true;
51
+ };
52
+ };
53
+ export declare function handler(input: Input, ctx: ToolContext): Promise<import("../../helpers/format.js").ToolTextResult>;
@@ -0,0 +1,54 @@
1
+ import { z } from "zod";
2
+ import { assertAllowed } from "../../config.js";
3
+ import { metaIdSchema, paginationShape } from "../../helpers/schema.js";
4
+ import { runList } from "../shared.js";
5
+ export const inputSchema = z
6
+ .object({
7
+ page_id: metaIdSchema,
8
+ edge: z
9
+ .enum(["posts", "published_posts", "feed"])
10
+ .default("published_posts")
11
+ .describe("'published_posts' is the standard edge. 'feed' includes user-posted items too."),
12
+ since: z.string().optional().describe("Unix timestamp or ISO date lower bound."),
13
+ until: z.string().optional().describe("Unix timestamp or ISO date upper bound."),
14
+ fields: z
15
+ .array(z.string())
16
+ .default([
17
+ "id",
18
+ "message",
19
+ "created_time",
20
+ "updated_time",
21
+ "permalink_url",
22
+ "status_type",
23
+ "type",
24
+ "is_published",
25
+ "from",
26
+ "attachments{media_type,title,url,subattachments}",
27
+ "reactions.summary(true).limit(0)",
28
+ "shares",
29
+ "comments.summary(true).limit(0)",
30
+ ])
31
+ .describe("Post fields. Default includes reaction + comment counts via summary."),
32
+ ...paginationShape,
33
+ })
34
+ .strict();
35
+ export const definition = {
36
+ name: "meta_page_list_posts",
37
+ title: "List Page posts",
38
+ description: `Lists Page posts with attached counts (reactions, comments, shares). Use since/until for a date window. The ID returned for each post is the one meta_page_get_post_insights expects.`,
39
+ inputSchema: inputSchema.shape,
40
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
41
+ };
42
+ export async function handler(input, ctx) {
43
+ assertAllowed("page", input.page_id, ctx.config);
44
+ return runList(ctx, {
45
+ path: `${input.page_id}/${input.edge}`,
46
+ params: {
47
+ fields: input.fields.join(","),
48
+ limit: input.limit,
49
+ after: input.after,
50
+ since: input.since,
51
+ until: input.until,
52
+ },
53
+ }, { auto_paginate: input.auto_paginate, after: input.after, limit: input.limit }, { page_id: input.page_id, edge: input.edge });
54
+ }