@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,64 @@
1
+ import { z } from "zod";
2
+ import { assertAllowed } from "../../config.js";
3
+ import { adAccountIdSchema, paginationShape } from "../../helpers/schema.js";
4
+ import { runList } from "../shared.js";
5
+ export const inputSchema = z
6
+ .object({
7
+ ad_account_id: adAccountIdSchema,
8
+ effective_status: z
9
+ .array(z.enum([
10
+ "ACTIVE",
11
+ "PAUSED",
12
+ "DELETED",
13
+ "PENDING_REVIEW",
14
+ "DISAPPROVED",
15
+ "PREAPPROVED",
16
+ "PENDING_BILLING_INFO",
17
+ "CAMPAIGN_PAUSED",
18
+ "ARCHIVED",
19
+ "IN_PROCESS",
20
+ "WITH_ISSUES",
21
+ ]))
22
+ .optional()
23
+ .describe("Filter by effective_status. Omit to list all."),
24
+ fields: z
25
+ .array(z.string())
26
+ .default([
27
+ "id",
28
+ "name",
29
+ "objective",
30
+ "effective_status",
31
+ "status",
32
+ "daily_budget",
33
+ "lifetime_budget",
34
+ "budget_remaining",
35
+ "buying_type",
36
+ "special_ad_categories",
37
+ "start_time",
38
+ "stop_time",
39
+ "created_time",
40
+ "updated_time",
41
+ ])
42
+ .describe("Campaign fields."),
43
+ ...paginationShape,
44
+ })
45
+ .strict();
46
+ export const definition = {
47
+ name: "meta_ads_list_campaigns",
48
+ title: "List campaigns in an ad account",
49
+ description: `Lists campaigns with status, objective, budget, and schedule. Use effective_status to filter only ACTIVE campaigns, for example. Pair with meta_ads_get_insights at level='campaign' for performance metrics.`,
50
+ inputSchema: inputSchema.shape,
51
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
52
+ };
53
+ export async function handler(input, ctx) {
54
+ assertAllowed("ad_account", input.ad_account_id, ctx.config);
55
+ const params = {
56
+ fields: input.fields.join(","),
57
+ limit: input.limit,
58
+ after: input.after,
59
+ };
60
+ if (input.effective_status) {
61
+ params["effective_status"] = JSON.stringify(input.effective_status);
62
+ }
63
+ return runList(ctx, { path: `${input.ad_account_id}/campaigns`, params }, { auto_paginate: input.auto_paginate, after: input.after, limit: input.limit }, { ad_account_id: input.ad_account_id });
64
+ }
@@ -0,0 +1,41 @@
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
+ ad_account_id: z.ZodString;
8
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
9
+ }, "strict", z.ZodTypeAny, {
10
+ fields: string[];
11
+ limit: number;
12
+ auto_paginate: boolean;
13
+ ad_account_id: string;
14
+ after?: string | undefined;
15
+ }, {
16
+ ad_account_id: string;
17
+ fields?: string[] | undefined;
18
+ limit?: number | undefined;
19
+ after?: string | undefined;
20
+ auto_paginate?: boolean | undefined;
21
+ }>;
22
+ export type Input = z.infer<typeof inputSchema>;
23
+ export declare const definition: {
24
+ readonly name: "meta_ads_list_custom_audiences";
25
+ readonly title: "List custom audiences (metadata only)";
26
+ readonly description: "Lists custom audiences attached to an ad account — names, subtype (CUSTOM, WEBSITE, LOOKALIKE, …), approximate size buckets, delivery status, data source. No member-level data is exposed.";
27
+ readonly inputSchema: {
28
+ limit: z.ZodDefault<z.ZodNumber>;
29
+ after: z.ZodOptional<z.ZodString>;
30
+ auto_paginate: z.ZodDefault<z.ZodBoolean>;
31
+ ad_account_id: z.ZodString;
32
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
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,41 @@
1
+ import { z } from "zod";
2
+ import { assertAllowed } from "../../config.js";
3
+ import { adAccountIdSchema, paginationShape } from "../../helpers/schema.js";
4
+ import { runList } from "../shared.js";
5
+ export const inputSchema = z
6
+ .object({
7
+ ad_account_id: adAccountIdSchema,
8
+ fields: z
9
+ .array(z.string())
10
+ .default([
11
+ "id",
12
+ "name",
13
+ "description",
14
+ "subtype",
15
+ "approximate_count_lower_bound",
16
+ "approximate_count_upper_bound",
17
+ "delivery_status",
18
+ "operation_status",
19
+ "data_source",
20
+ "retention_days",
21
+ "time_created",
22
+ "time_updated",
23
+ ])
24
+ .describe("Metadata fields. No PII/member data is returned by this endpoint."),
25
+ ...paginationShape,
26
+ })
27
+ .strict();
28
+ export const definition = {
29
+ name: "meta_ads_list_custom_audiences",
30
+ title: "List custom audiences (metadata only)",
31
+ description: `Lists custom audiences attached to an ad account — names, subtype (CUSTOM, WEBSITE, LOOKALIKE, …), approximate size buckets, delivery status, data source. No member-level data is exposed.`,
32
+ inputSchema: inputSchema.shape,
33
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
34
+ };
35
+ export async function handler(input, ctx) {
36
+ assertAllowed("ad_account", input.ad_account_id, ctx.config);
37
+ return runList(ctx, {
38
+ path: `${input.ad_account_id}/customaudiences`,
39
+ params: { fields: input.fields.join(","), limit: input.limit, after: input.after },
40
+ }, { auto_paginate: input.auto_paginate, after: input.after, limit: input.limit }, { ad_account_id: input.ad_account_id });
41
+ }
@@ -0,0 +1,37 @@
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
+ kinds: z.ZodDefault<z.ZodArray<z.ZodEnum<["ad_accounts", "pages", "instagram_accounts", "pixels", "product_catalogs", "whatsapp_business_accounts"]>, "many">>;
6
+ include_client: z.ZodDefault<z.ZodBoolean>;
7
+ per_kind_limit: z.ZodDefault<z.ZodNumber>;
8
+ }, "strict", z.ZodTypeAny, {
9
+ business_id: string;
10
+ kinds: ("pages" | "ad_accounts" | "instagram_accounts" | "pixels" | "product_catalogs" | "whatsapp_business_accounts")[];
11
+ include_client: boolean;
12
+ per_kind_limit: number;
13
+ }, {
14
+ business_id: string;
15
+ kinds?: ("pages" | "ad_accounts" | "instagram_accounts" | "pixels" | "product_catalogs" | "whatsapp_business_accounts")[] | undefined;
16
+ include_client?: boolean | undefined;
17
+ per_kind_limit?: number | undefined;
18
+ }>;
19
+ export type Input = z.infer<typeof inputSchema>;
20
+ export declare const definition: {
21
+ readonly name: "meta_business_list_assets";
22
+ readonly title: "List assets assigned to a Business Manager";
23
+ readonly description: "For a given business_id, enumerates the business assets the token can see in one call:\n- Ad accounts (owned + optionally client)\n- Facebook Pages (owned + optionally client)\n- Instagram Business accounts\n- Meta Pixels\n- Product catalogs\n- WhatsApp Business accounts (WABAs)\n\nEach section is fetched as a separate Graph call. Failures on individual sections do not abort the others — the response reports per-section success/error so the assistant can work around partial failures.\n\nUse this to discover IDs for downstream insight tools.";
24
+ readonly inputSchema: {
25
+ business_id: z.ZodString;
26
+ kinds: z.ZodDefault<z.ZodArray<z.ZodEnum<["ad_accounts", "pages", "instagram_accounts", "pixels", "product_catalogs", "whatsapp_business_accounts"]>, "many">>;
27
+ include_client: z.ZodDefault<z.ZodBoolean>;
28
+ per_kind_limit: z.ZodDefault<z.ZodNumber>;
29
+ };
30
+ readonly annotations: {
31
+ readonly readOnlyHint: true;
32
+ readonly destructiveHint: false;
33
+ readonly idempotentHint: true;
34
+ readonly openWorldHint: true;
35
+ };
36
+ };
37
+ export declare function handler(input: Input, ctx: ToolContext): Promise<import("../../helpers/format.js").ToolTextResult>;
@@ -0,0 +1,136 @@
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 { metaIdSchema } from "../../helpers/schema.js";
6
+ const ASSET_KINDS = [
7
+ "ad_accounts",
8
+ "pages",
9
+ "instagram_accounts",
10
+ "pixels",
11
+ "product_catalogs",
12
+ "whatsapp_business_accounts",
13
+ ];
14
+ export const inputSchema = z
15
+ .object({
16
+ business_id: metaIdSchema.describe("Business Manager ID (from meta_business_list)."),
17
+ kinds: z
18
+ .array(z.enum(ASSET_KINDS))
19
+ .default([...ASSET_KINDS])
20
+ .describe("Which asset edges to enumerate. Default: all."),
21
+ include_client: z
22
+ .boolean()
23
+ .default(false)
24
+ .describe("Also fetch client_* edges (assets the business has access to but does not own)."),
25
+ per_kind_limit: z
26
+ .number()
27
+ .int()
28
+ .min(1)
29
+ .max(500)
30
+ .default(50)
31
+ .describe("Page size per asset kind."),
32
+ })
33
+ .strict();
34
+ export const definition = {
35
+ name: "meta_business_list_assets",
36
+ title: "List assets assigned to a Business Manager",
37
+ description: `For a given business_id, enumerates the business assets the token can see in one call:
38
+ - Ad accounts (owned + optionally client)
39
+ - Facebook Pages (owned + optionally client)
40
+ - Instagram Business accounts
41
+ - Meta Pixels
42
+ - Product catalogs
43
+ - WhatsApp Business accounts (WABAs)
44
+
45
+ Each section is fetched as a separate Graph call. Failures on individual sections do not abort the others — the response reports per-section success/error so the assistant can work around partial failures.
46
+
47
+ Use this to discover IDs for downstream insight tools.`,
48
+ inputSchema: inputSchema.shape,
49
+ annotations: {
50
+ readOnlyHint: true,
51
+ destructiveHint: false,
52
+ idempotentHint: true,
53
+ openWorldHint: true,
54
+ },
55
+ };
56
+ const FIELDS = {
57
+ ad_accounts: "id,account_id,name,currency,timezone_name,account_status",
58
+ pages: "id,name,category,tasks,access_token",
59
+ instagram_accounts: "id,username",
60
+ pixels: "id,name,last_fired_time,is_unavailable",
61
+ product_catalogs: "id,name,vertical,product_count",
62
+ whatsapp_business_accounts: "id,name,currency,timezone_id",
63
+ };
64
+ const EDGE_NAME = {
65
+ ad_accounts: { owned: "owned_ad_accounts", client: "client_ad_accounts" },
66
+ pages: { owned: "owned_pages", client: "client_pages" },
67
+ // Graph exposes `owned_instagram_accounts` on the Business node but not a
68
+ // `client_instagram_accounts` edge. IG accounts linked to a Page are also
69
+ // discoverable via `GET /{page_id}?fields=instagram_business_account`.
70
+ instagram_accounts: { owned: "owned_instagram_accounts", client: null },
71
+ pixels: { owned: "owned_pixels", client: null },
72
+ product_catalogs: { owned: "owned_product_catalogs", client: "client_product_catalogs" },
73
+ whatsapp_business_accounts: { owned: "owned_whatsapp_business_accounts", client: "client_whatsapp_business_accounts" },
74
+ };
75
+ export async function handler(input, ctx) {
76
+ assertAllowed("business", input.business_id, ctx.config);
77
+ const scopes = input.include_client ? ["owned", "client"] : ["owned"];
78
+ const sections = {};
79
+ await Promise.all(input.kinds.flatMap((kind) => scopes.map(async (scope) => {
80
+ const edge = EDGE_NAME[kind][scope];
81
+ if (!edge)
82
+ return;
83
+ const section = (sections[kind] ??= []);
84
+ try {
85
+ const page = await ctx.graph.get({
86
+ path: `${input.business_id}/${edge}`,
87
+ params: { fields: FIELDS[kind], limit: input.per_kind_limit },
88
+ });
89
+ section.push({ scope, items: Array.isArray(page.data) ? page.data : [] });
90
+ }
91
+ catch (err) {
92
+ const e = err instanceof MetaError ? err : new MetaError(err.message);
93
+ section.push({ scope, error: e.message, hint: e.hint });
94
+ }
95
+ })));
96
+ // Fallback IG discovery: walk the surviving Pages and look up
97
+ // `instagram_business_account`. Meta increasingly hides IG behind the Page
98
+ // link rather than the Business node.
99
+ if (input.kinds.includes("instagram_accounts")) {
100
+ const pageSection = sections.pages ?? [];
101
+ const pageItems = pageSection.flatMap((s) => s.items ?? []);
102
+ const igFromPages = [];
103
+ await Promise.all(pageItems.map(async (p) => {
104
+ try {
105
+ const data = await ctx.graph.get({
106
+ path: p.id,
107
+ params: { fields: "id,name,instagram_business_account{id,username,name}" },
108
+ });
109
+ if (data.instagram_business_account) {
110
+ igFromPages.push({
111
+ id: data.instagram_business_account.id,
112
+ name: data.instagram_business_account.name,
113
+ username: data.instagram_business_account.username,
114
+ category: `via page ${data.id} (${data.name ?? ""})`.trim(),
115
+ });
116
+ }
117
+ }
118
+ catch {
119
+ /* non-fatal per-page */
120
+ }
121
+ }));
122
+ if (igFromPages.length > 0) {
123
+ (sections.instagram_accounts ??= []).push({
124
+ scope: "via_page",
125
+ items: igFromPages,
126
+ source: "page.instagram_business_account",
127
+ });
128
+ }
129
+ }
130
+ const structured = {
131
+ business_id: input.business_id,
132
+ scopes,
133
+ assets: sections,
134
+ };
135
+ return toolResult(structured, jsonBlock(structured));
136
+ }
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ import type { ToolContext } from "../../context.js";
3
+ export declare const inputSchema: z.ZodObject<{
4
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
5
+ limit: z.ZodDefault<z.ZodNumber>;
6
+ after: z.ZodOptional<z.ZodString>;
7
+ auto_paginate: z.ZodDefault<z.ZodBoolean>;
8
+ }, "strict", z.ZodTypeAny, {
9
+ fields: string[];
10
+ limit: number;
11
+ auto_paginate: boolean;
12
+ after?: string | undefined;
13
+ }, {
14
+ fields?: string[] | undefined;
15
+ limit?: number | undefined;
16
+ after?: string | undefined;
17
+ auto_paginate?: boolean | undefined;
18
+ }>;
19
+ export type Input = z.infer<typeof inputSchema>;
20
+ export declare const definition: {
21
+ readonly name: "meta_business_list";
22
+ readonly title: "List Meta businesses visible to the token";
23
+ readonly description: "Lists every Business Manager the configured access token can see — via GET /me/businesses.\n\nTypical usage: call this once at the start of a session to discover available business IDs, then pass the chosen ID to meta_business_list_assets / meta_business_list_system_users.\n\nRespects META_ALLOWED_BUSINESS_IDS: if set, filters the response to that allowlist.";
24
+ readonly inputSchema: {
25
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
26
+ limit: z.ZodDefault<z.ZodNumber>;
27
+ after: z.ZodOptional<z.ZodString>;
28
+ auto_paginate: z.ZodDefault<z.ZodBoolean>;
29
+ };
30
+ readonly annotations: {
31
+ readonly readOnlyHint: true;
32
+ readonly destructiveHint: false;
33
+ readonly idempotentHint: true;
34
+ readonly openWorldHint: true;
35
+ };
36
+ };
37
+ export declare function handler(input: Input, ctx: ToolContext): Promise<import("../../helpers/format.js").ToolTextResult>;
@@ -0,0 +1,81 @@
1
+ import { z } from "zod";
2
+ import { assertAllowed } from "../../config.js";
3
+ import { MetaError } from "../../errors.js";
4
+ import { jsonBlock, toolError, toolResult } from "../../helpers/format.js";
5
+ import { paginationShape } from "../../helpers/schema.js";
6
+ export const inputSchema = z
7
+ .object({
8
+ ...paginationShape,
9
+ fields: z
10
+ .array(z.string())
11
+ .default([
12
+ "id",
13
+ "name",
14
+ "verification_status",
15
+ "primary_page",
16
+ "created_time",
17
+ "updated_time",
18
+ "timezone_id",
19
+ ])
20
+ .describe("Fields to request on each business."),
21
+ })
22
+ .strict();
23
+ export const definition = {
24
+ name: "meta_business_list",
25
+ title: "List Meta businesses visible to the token",
26
+ description: `Lists every Business Manager the configured access token can see — via GET /me/businesses.
27
+
28
+ Typical usage: call this once at the start of a session to discover available business IDs, then pass the chosen ID to meta_business_list_assets / meta_business_list_system_users.
29
+
30
+ Respects META_ALLOWED_BUSINESS_IDS: if set, filters the response to that allowlist.`,
31
+ inputSchema: inputSchema.shape,
32
+ annotations: {
33
+ readOnlyHint: true,
34
+ destructiveHint: false,
35
+ idempotentHint: true,
36
+ openWorldHint: true,
37
+ },
38
+ };
39
+ export async function handler(input, ctx) {
40
+ try {
41
+ const params = {
42
+ fields: input.fields.join(","),
43
+ limit: input.limit,
44
+ after: input.after,
45
+ };
46
+ const opts = { path: "me/businesses", params };
47
+ const { data, pages, nextAfter } = input.auto_paginate
48
+ ? await ctx.graph.getAllPages(opts)
49
+ : await singlePage(ctx, opts);
50
+ const allowlist = ctx.config.allowedBusinessIds;
51
+ const filtered = allowlist ? data.filter((b) => allowlist.has(b.id)) : data;
52
+ // Sanity-check that whatever survived the allowlist is allowed.
53
+ for (const b of filtered)
54
+ assertAllowed("business", b.id, ctx.config);
55
+ const structured = {
56
+ count: filtered.length,
57
+ pages_fetched: pages,
58
+ next_after: nextAfter,
59
+ businesses: filtered,
60
+ filtered_by_allowlist: Boolean(allowlist),
61
+ };
62
+ return toolResult(structured, jsonBlock(structured));
63
+ }
64
+ catch (err) {
65
+ const e = err instanceof MetaError ? err : new MetaError(err.message);
66
+ return toolError(e.message, e.hint, {
67
+ code: e.code,
68
+ subcode: e.subcode,
69
+ fbtrace_id: e.fbtraceId,
70
+ http_status: e.httpStatus,
71
+ });
72
+ }
73
+ }
74
+ async function singlePage(ctx, opts) {
75
+ const page = await ctx.graph.get(opts);
76
+ return {
77
+ data: Array.isArray(page.data) ? page.data : [],
78
+ pages: 1,
79
+ nextAfter: page.paging?.cursors?.after,
80
+ };
81
+ }
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ import type { ToolContext } from "../../context.js";
3
+ export declare const inputSchema: z.ZodObject<{
4
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
5
+ limit: z.ZodDefault<z.ZodNumber>;
6
+ after: z.ZodOptional<z.ZodString>;
7
+ auto_paginate: z.ZodDefault<z.ZodBoolean>;
8
+ business_id: z.ZodString;
9
+ }, "strict", z.ZodTypeAny, {
10
+ fields: string[];
11
+ limit: number;
12
+ auto_paginate: boolean;
13
+ business_id: string;
14
+ after?: string | undefined;
15
+ }, {
16
+ business_id: string;
17
+ fields?: string[] | undefined;
18
+ limit?: number | undefined;
19
+ after?: string | undefined;
20
+ auto_paginate?: boolean | undefined;
21
+ }>;
22
+ export type Input = z.infer<typeof inputSchema>;
23
+ export declare const definition: {
24
+ readonly name: "meta_business_list_system_users";
25
+ readonly title: "List system users attached to a business";
26
+ readonly description: "Lists the system-user (server/software) identities under a Business Manager.\n\nSystem users are non-human identities used for API access. This tool helps diagnose which identity owns the token in use (cross-reference with meta_token_inspect).\n\nReads /{business_id}/system_users.";
27
+ readonly inputSchema: {
28
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
29
+ limit: z.ZodDefault<z.ZodNumber>;
30
+ after: z.ZodOptional<z.ZodString>;
31
+ auto_paginate: z.ZodDefault<z.ZodBoolean>;
32
+ business_id: 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,73 @@
1
+ import { z } from "zod";
2
+ import { assertAllowed } from "../../config.js";
3
+ import { MetaError } from "../../errors.js";
4
+ import { jsonBlock, toolError, toolResult } from "../../helpers/format.js";
5
+ import { metaIdSchema, paginationShape } from "../../helpers/schema.js";
6
+ export const inputSchema = z
7
+ .object({
8
+ business_id: metaIdSchema.describe("Business Manager ID."),
9
+ ...paginationShape,
10
+ fields: z
11
+ .array(z.string())
12
+ .default(["id", "name", "role", "finance_role", "ip_role"])
13
+ .describe("Fields to return for each system user."),
14
+ })
15
+ .strict();
16
+ export const definition = {
17
+ name: "meta_business_list_system_users",
18
+ title: "List system users attached to a business",
19
+ description: `Lists the system-user (server/software) identities under a Business Manager.
20
+
21
+ System users are non-human identities used for API access. This tool helps diagnose which identity owns the token in use (cross-reference with meta_token_inspect).
22
+
23
+ Reads /{business_id}/system_users.`,
24
+ inputSchema: inputSchema.shape,
25
+ annotations: {
26
+ readOnlyHint: true,
27
+ destructiveHint: false,
28
+ idempotentHint: true,
29
+ openWorldHint: true,
30
+ },
31
+ };
32
+ export async function handler(input, ctx) {
33
+ assertAllowed("business", input.business_id, ctx.config);
34
+ try {
35
+ const opts = {
36
+ path: `${input.business_id}/system_users`,
37
+ params: {
38
+ fields: input.fields.join(","),
39
+ limit: input.limit,
40
+ after: input.after,
41
+ },
42
+ };
43
+ if (input.auto_paginate) {
44
+ const { data, pages, nextAfter } = await ctx.graph.getAllPages(opts);
45
+ const structured = {
46
+ business_id: input.business_id,
47
+ count: data.length,
48
+ pages_fetched: pages,
49
+ next_after: nextAfter,
50
+ system_users: data,
51
+ };
52
+ return toolResult(structured, jsonBlock(structured));
53
+ }
54
+ const page = await ctx.graph.get(opts);
55
+ const structured = {
56
+ business_id: input.business_id,
57
+ count: Array.isArray(page.data) ? page.data.length : 0,
58
+ pages_fetched: 1,
59
+ next_after: page.paging?.cursors?.after,
60
+ system_users: page.data ?? [],
61
+ };
62
+ return toolResult(structured, jsonBlock(structured));
63
+ }
64
+ catch (err) {
65
+ const e = err instanceof MetaError ? err : new MetaError(err.message);
66
+ return toolError(e.message, e.hint, {
67
+ code: e.code,
68
+ subcode: e.subcode,
69
+ fbtrace_id: e.fbtraceId,
70
+ http_status: e.httpStatus,
71
+ });
72
+ }
73
+ }
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ import type { ToolContext } from "../../context.js";
3
+ export declare const inputSchema: z.ZodObject<{
4
+ catalog_id: z.ZodString;
5
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
6
+ }, "strict", z.ZodTypeAny, {
7
+ fields: string[];
8
+ catalog_id: string;
9
+ }, {
10
+ catalog_id: string;
11
+ fields?: string[] | undefined;
12
+ }>;
13
+ export type Input = z.infer<typeof inputSchema>;
14
+ export declare const definition: {
15
+ readonly name: "meta_catalog_get_diagnostics";
16
+ readonly title: "Get catalog diagnostics";
17
+ readonly description: "Surfaces catalog issues: disapproved items, missing required fields, GTIN problems, image errors. Pair with meta_catalog_list_products to see affected items.";
18
+ readonly inputSchema: {
19
+ catalog_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,26 @@
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
+ catalog_id: metaIdSchema,
7
+ fields: z
8
+ .array(z.string())
9
+ .default([
10
+ "diagnostics{severity,type,title,description,affected_items,affected_channels}",
11
+ "product_count",
12
+ "feed_count",
13
+ ])
14
+ .describe("Diagnostics fields. Meta surfaces issues like missing images, disapproved items, incomplete GTIN, etc."),
15
+ })
16
+ .strict();
17
+ export const definition = {
18
+ name: "meta_catalog_get_diagnostics",
19
+ title: "Get catalog diagnostics",
20
+ description: `Surfaces catalog issues: disapproved items, missing required fields, GTIN problems, image errors. Pair with meta_catalog_list_products to see affected items.`,
21
+ inputSchema: inputSchema.shape,
22
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
23
+ };
24
+ export async function handler(input, ctx) {
25
+ return runGet(ctx, { path: input.catalog_id, params: { fields: input.fields.join(",") } });
26
+ }
@@ -0,0 +1,45 @@
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
+ catalog_id: z.ZodString;
8
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
9
+ filter: z.ZodOptional<z.ZodString>;
10
+ }, "strict", z.ZodTypeAny, {
11
+ fields: string[];
12
+ limit: number;
13
+ auto_paginate: boolean;
14
+ catalog_id: string;
15
+ filter?: string | undefined;
16
+ after?: string | undefined;
17
+ }, {
18
+ catalog_id: string;
19
+ filter?: string | undefined;
20
+ fields?: string[] | undefined;
21
+ limit?: number | undefined;
22
+ after?: string | undefined;
23
+ auto_paginate?: boolean | undefined;
24
+ }>;
25
+ export type Input = z.infer<typeof inputSchema>;
26
+ export declare const definition: {
27
+ readonly name: "meta_catalog_list_products";
28
+ readonly title: "List products in a catalog";
29
+ readonly description: "Lists products with name, retailer_id, price, availability, review_status. Filter by availability/category via the 'filter' param (raw JSON string per Meta spec).";
30
+ readonly inputSchema: {
31
+ limit: z.ZodDefault<z.ZodNumber>;
32
+ after: z.ZodOptional<z.ZodString>;
33
+ auto_paginate: z.ZodDefault<z.ZodBoolean>;
34
+ catalog_id: z.ZodString;
35
+ fields: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
36
+ filter: z.ZodOptional<z.ZodString>;
37
+ };
38
+ readonly annotations: {
39
+ readonly readOnlyHint: true;
40
+ readonly destructiveHint: false;
41
+ readonly idempotentHint: true;
42
+ readonly openWorldHint: true;
43
+ };
44
+ };
45
+ export declare function handler(input: Input, ctx: ToolContext): Promise<import("../../helpers/format.js").ToolTextResult>;