posterly-mcp-server 0.40.0 → 0.43.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.
@@ -1,6 +1,12 @@
1
1
  import { z } from 'zod';
2
2
  import { dashboardUrlForPost, formatLocalDateTime } from '../lib/format.js';
3
3
  import { SUPPORTED_PLATFORM_INPUTS, SUPPORTED_PLATFORM_IDS } from '../generated/platform-manifest.js';
4
+ const mediaAccessibilitySchema = z.array(z.object({
5
+ index: z.number().int().nonnegative(),
6
+ asset_id: z.string().optional(),
7
+ source_url: z.string().url().optional(),
8
+ alt_text: z.string(),
9
+ })).describe('Preferred ordered media alt text. Identity follows index/asset_id through platform media preparation; media_alt_texts remains the legacy URL-map form.');
4
10
  export const instagramSettingsSchema = z.object({
5
11
  __type: z.enum(['instagram', 'instagram-standalone']).optional(),
6
12
  post_type: z.enum(['post', 'feed', 'story', 'reel', 'carousel']).optional(),
@@ -17,6 +23,7 @@ export const instagramSettingsSchema = z.object({
17
23
  .describe('Native clickable media tags, not caption @mentions. Supported by eligible direct Instagram and Meta-linked connections; feed images, Reels/video, and Stories. Tags apply to each carousel item and the first Story in a Story Series.'),
18
24
  first_comment: z.string().optional(),
19
25
  media_alt_texts: z.record(z.string(), z.string()).optional(),
26
+ media_accessibility: mediaAccessibilitySchema.optional(),
20
27
  reel_cover_url: z.string().optional(),
21
28
  reel_thumb_offset: z.number().nonnegative().optional(),
22
29
  is_ai_generated: z.boolean().optional().describe('Label the parent Instagram media container as AI-generated. For carousels, set on the parent only.'),
@@ -27,6 +34,7 @@ export const platformSettingsSchema = z.object({
27
34
  post_type: z.string().optional(),
28
35
  content_type: z.string().optional(),
29
36
  media_alt_texts: z.record(z.string(), z.string()).optional(),
37
+ media_accessibility: mediaAccessibilitySchema.optional(),
30
38
  reel_cover_url: z.string().optional(),
31
39
  reel_thumb_offset: z.number().nonnegative().optional(),
32
40
  // X
@@ -48,6 +48,22 @@ export declare const createPostsBatchTool: {
48
48
  }>]>, "many">>;
49
49
  first_comment: z.ZodOptional<z.ZodString>;
50
50
  media_alt_texts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
51
+ media_accessibility: z.ZodOptional<z.ZodArray<z.ZodObject<{
52
+ index: z.ZodNumber;
53
+ asset_id: z.ZodOptional<z.ZodString>;
54
+ source_url: z.ZodOptional<z.ZodString>;
55
+ alt_text: z.ZodString;
56
+ }, "strip", z.ZodTypeAny, {
57
+ index: number;
58
+ alt_text: string;
59
+ asset_id?: string | undefined;
60
+ source_url?: string | undefined;
61
+ }, {
62
+ index: number;
63
+ alt_text: string;
64
+ asset_id?: string | undefined;
65
+ source_url?: string | undefined;
66
+ }>, "many">>;
51
67
  reel_cover_url: z.ZodOptional<z.ZodString>;
52
68
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
53
69
  is_ai_generated: z.ZodOptional<z.ZodBoolean>;
@@ -71,6 +87,12 @@ export declare const createPostsBatchTool: {
71
87
  })[] | undefined;
72
88
  first_comment?: string | undefined;
73
89
  media_alt_texts?: Record<string, string> | undefined;
90
+ media_accessibility?: {
91
+ index: number;
92
+ alt_text: string;
93
+ asset_id?: string | undefined;
94
+ source_url?: string | undefined;
95
+ }[] | undefined;
74
96
  is_ai_generated?: boolean | undefined;
75
97
  audio_id?: string | undefined;
76
98
  }, {
@@ -92,6 +114,12 @@ export declare const createPostsBatchTool: {
92
114
  })[] | undefined;
93
115
  first_comment?: string | undefined;
94
116
  media_alt_texts?: Record<string, string> | undefined;
117
+ media_accessibility?: {
118
+ index: number;
119
+ alt_text: string;
120
+ asset_id?: string | undefined;
121
+ source_url?: string | undefined;
122
+ }[] | undefined;
95
123
  is_ai_generated?: boolean | undefined;
96
124
  audio_id?: string | undefined;
97
125
  }>>;
@@ -100,6 +128,22 @@ export declare const createPostsBatchTool: {
100
128
  post_type: z.ZodOptional<z.ZodString>;
101
129
  content_type: z.ZodOptional<z.ZodString>;
102
130
  media_alt_texts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
131
+ media_accessibility: z.ZodOptional<z.ZodArray<z.ZodObject<{
132
+ index: z.ZodNumber;
133
+ asset_id: z.ZodOptional<z.ZodString>;
134
+ source_url: z.ZodOptional<z.ZodString>;
135
+ alt_text: z.ZodString;
136
+ }, "strip", z.ZodTypeAny, {
137
+ index: number;
138
+ alt_text: string;
139
+ asset_id?: string | undefined;
140
+ source_url?: string | undefined;
141
+ }, {
142
+ index: number;
143
+ alt_text: string;
144
+ asset_id?: string | undefined;
145
+ source_url?: string | undefined;
146
+ }>, "many">>;
103
147
  reel_cover_url: z.ZodOptional<z.ZodString>;
104
148
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
105
149
  reply_settings: z.ZodOptional<z.ZodEnum<["everyone", "following", "mentionedUsers", "subscribers", "verified"]>>;
@@ -207,6 +251,22 @@ export declare const createPostsBatchTool: {
207
251
  post_type: z.ZodOptional<z.ZodString>;
208
252
  content_type: z.ZodOptional<z.ZodString>;
209
253
  media_alt_texts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
254
+ media_accessibility: z.ZodOptional<z.ZodArray<z.ZodObject<{
255
+ index: z.ZodNumber;
256
+ asset_id: z.ZodOptional<z.ZodString>;
257
+ source_url: z.ZodOptional<z.ZodString>;
258
+ alt_text: z.ZodString;
259
+ }, "strip", z.ZodTypeAny, {
260
+ index: number;
261
+ alt_text: string;
262
+ asset_id?: string | undefined;
263
+ source_url?: string | undefined;
264
+ }, {
265
+ index: number;
266
+ alt_text: string;
267
+ asset_id?: string | undefined;
268
+ source_url?: string | undefined;
269
+ }>, "many">>;
210
270
  reel_cover_url: z.ZodOptional<z.ZodString>;
211
271
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
212
272
  reply_settings: z.ZodOptional<z.ZodEnum<["everyone", "following", "mentionedUsers", "subscribers", "verified"]>>;
@@ -314,6 +374,22 @@ export declare const createPostsBatchTool: {
314
374
  post_type: z.ZodOptional<z.ZodString>;
315
375
  content_type: z.ZodOptional<z.ZodString>;
316
376
  media_alt_texts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
377
+ media_accessibility: z.ZodOptional<z.ZodArray<z.ZodObject<{
378
+ index: z.ZodNumber;
379
+ asset_id: z.ZodOptional<z.ZodString>;
380
+ source_url: z.ZodOptional<z.ZodString>;
381
+ alt_text: z.ZodString;
382
+ }, "strip", z.ZodTypeAny, {
383
+ index: number;
384
+ alt_text: string;
385
+ asset_id?: string | undefined;
386
+ source_url?: string | undefined;
387
+ }, {
388
+ index: number;
389
+ alt_text: string;
390
+ asset_id?: string | undefined;
391
+ source_url?: string | undefined;
392
+ }>, "many">>;
317
393
  reel_cover_url: z.ZodOptional<z.ZodString>;
318
394
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
319
395
  reply_settings: z.ZodOptional<z.ZodEnum<["everyone", "following", "mentionedUsers", "subscribers", "verified"]>>;
@@ -448,6 +524,12 @@ export declare const createPostsBatchTool: {
448
524
  })[] | undefined;
449
525
  first_comment?: string | undefined;
450
526
  media_alt_texts?: Record<string, string> | undefined;
527
+ media_accessibility?: {
528
+ index: number;
529
+ alt_text: string;
530
+ asset_id?: string | undefined;
531
+ source_url?: string | undefined;
532
+ }[] | undefined;
451
533
  is_ai_generated?: boolean | undefined;
452
534
  audio_id?: string | undefined;
453
535
  } | undefined;
@@ -456,6 +538,22 @@ export declare const createPostsBatchTool: {
456
538
  post_type: z.ZodOptional<z.ZodString>;
457
539
  content_type: z.ZodOptional<z.ZodString>;
458
540
  media_alt_texts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
541
+ media_accessibility: z.ZodOptional<z.ZodArray<z.ZodObject<{
542
+ index: z.ZodNumber;
543
+ asset_id: z.ZodOptional<z.ZodString>;
544
+ source_url: z.ZodOptional<z.ZodString>;
545
+ alt_text: z.ZodString;
546
+ }, "strip", z.ZodTypeAny, {
547
+ index: number;
548
+ alt_text: string;
549
+ asset_id?: string | undefined;
550
+ source_url?: string | undefined;
551
+ }, {
552
+ index: number;
553
+ alt_text: string;
554
+ asset_id?: string | undefined;
555
+ source_url?: string | undefined;
556
+ }>, "many">>;
459
557
  reel_cover_url: z.ZodOptional<z.ZodString>;
460
558
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
461
559
  reply_settings: z.ZodOptional<z.ZodEnum<["everyone", "following", "mentionedUsers", "subscribers", "verified"]>>;
@@ -589,6 +687,12 @@ export declare const createPostsBatchTool: {
589
687
  })[] | undefined;
590
688
  first_comment?: string | undefined;
591
689
  media_alt_texts?: Record<string, string> | undefined;
690
+ media_accessibility?: {
691
+ index: number;
692
+ alt_text: string;
693
+ asset_id?: string | undefined;
694
+ source_url?: string | undefined;
695
+ }[] | undefined;
592
696
  is_ai_generated?: boolean | undefined;
593
697
  audio_id?: string | undefined;
594
698
  } | undefined;
@@ -597,6 +701,22 @@ export declare const createPostsBatchTool: {
597
701
  post_type: z.ZodOptional<z.ZodString>;
598
702
  content_type: z.ZodOptional<z.ZodString>;
599
703
  media_alt_texts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
704
+ media_accessibility: z.ZodOptional<z.ZodArray<z.ZodObject<{
705
+ index: z.ZodNumber;
706
+ asset_id: z.ZodOptional<z.ZodString>;
707
+ source_url: z.ZodOptional<z.ZodString>;
708
+ alt_text: z.ZodString;
709
+ }, "strip", z.ZodTypeAny, {
710
+ index: number;
711
+ alt_text: string;
712
+ asset_id?: string | undefined;
713
+ source_url?: string | undefined;
714
+ }, {
715
+ index: number;
716
+ alt_text: string;
717
+ asset_id?: string | undefined;
718
+ source_url?: string | undefined;
719
+ }>, "many">>;
600
720
  reel_cover_url: z.ZodOptional<z.ZodString>;
601
721
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
602
722
  reply_settings: z.ZodOptional<z.ZodEnum<["everyone", "following", "mentionedUsers", "subscribers", "verified"]>>;
@@ -734,6 +854,12 @@ export declare const createPostsBatchTool: {
734
854
  })[] | undefined;
735
855
  first_comment?: string | undefined;
736
856
  media_alt_texts?: Record<string, string> | undefined;
857
+ media_accessibility?: {
858
+ index: number;
859
+ alt_text: string;
860
+ asset_id?: string | undefined;
861
+ source_url?: string | undefined;
862
+ }[] | undefined;
737
863
  is_ai_generated?: boolean | undefined;
738
864
  audio_id?: string | undefined;
739
865
  } | undefined;
@@ -742,6 +868,22 @@ export declare const createPostsBatchTool: {
742
868
  post_type: z.ZodOptional<z.ZodString>;
743
869
  content_type: z.ZodOptional<z.ZodString>;
744
870
  media_alt_texts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
871
+ media_accessibility: z.ZodOptional<z.ZodArray<z.ZodObject<{
872
+ index: z.ZodNumber;
873
+ asset_id: z.ZodOptional<z.ZodString>;
874
+ source_url: z.ZodOptional<z.ZodString>;
875
+ alt_text: z.ZodString;
876
+ }, "strip", z.ZodTypeAny, {
877
+ index: number;
878
+ alt_text: string;
879
+ asset_id?: string | undefined;
880
+ source_url?: string | undefined;
881
+ }, {
882
+ index: number;
883
+ alt_text: string;
884
+ asset_id?: string | undefined;
885
+ source_url?: string | undefined;
886
+ }>, "many">>;
745
887
  reel_cover_url: z.ZodOptional<z.ZodString>;
746
888
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
747
889
  reply_settings: z.ZodOptional<z.ZodEnum<["everyone", "following", "mentionedUsers", "subscribers", "verified"]>>;
@@ -878,6 +1020,12 @@ export declare const createPostsBatchTool: {
878
1020
  })[] | undefined;
879
1021
  first_comment?: string | undefined;
880
1022
  media_alt_texts?: Record<string, string> | undefined;
1023
+ media_accessibility?: {
1024
+ index: number;
1025
+ alt_text: string;
1026
+ asset_id?: string | undefined;
1027
+ source_url?: string | undefined;
1028
+ }[] | undefined;
881
1029
  is_ai_generated?: boolean | undefined;
882
1030
  audio_id?: string | undefined;
883
1031
  } | undefined;
@@ -886,6 +1034,22 @@ export declare const createPostsBatchTool: {
886
1034
  post_type: z.ZodOptional<z.ZodString>;
887
1035
  content_type: z.ZodOptional<z.ZodString>;
888
1036
  media_alt_texts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1037
+ media_accessibility: z.ZodOptional<z.ZodArray<z.ZodObject<{
1038
+ index: z.ZodNumber;
1039
+ asset_id: z.ZodOptional<z.ZodString>;
1040
+ source_url: z.ZodOptional<z.ZodString>;
1041
+ alt_text: z.ZodString;
1042
+ }, "strip", z.ZodTypeAny, {
1043
+ index: number;
1044
+ alt_text: string;
1045
+ asset_id?: string | undefined;
1046
+ source_url?: string | undefined;
1047
+ }, {
1048
+ index: number;
1049
+ alt_text: string;
1050
+ asset_id?: string | undefined;
1051
+ source_url?: string | undefined;
1052
+ }>, "many">>;
889
1053
  reel_cover_url: z.ZodOptional<z.ZodString>;
890
1054
  reel_thumb_offset: z.ZodOptional<z.ZodNumber>;
891
1055
  reply_settings: z.ZodOptional<z.ZodEnum<["everyone", "following", "mentionedUsers", "subscribers", "verified"]>>;
@@ -11,7 +11,9 @@ export declare const generateImageTool: {
11
11
  provider: z.ZodOptional<z.ZodEnum<["google", "xai"]>>;
12
12
  model: z.ZodOptional<z.ZodEnum<["lite", "flash", "pro"]>>;
13
13
  resolution: z.ZodOptional<z.ZodEnum<["512", "1K", "2K", "4K"]>>;
14
- quality: z.ZodOptional<z.ZodEnum<["low", "medium"]>>;
14
+ quality: z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>;
15
+ thinking_level: z.ZodOptional<z.ZodEnum<["minimal", "high"]>>;
16
+ reference_image_urls: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
15
17
  confirm: z.ZodLiteral<true>;
16
18
  }, "strip", z.ZodTypeAny, {
17
19
  confirm: true;
@@ -22,7 +24,9 @@ export declare const generateImageTool: {
22
24
  variations?: number | undefined;
23
25
  model?: "pro" | "lite" | "flash" | undefined;
24
26
  resolution?: "512" | "1K" | "2K" | "4K" | undefined;
25
- quality?: "low" | "medium" | undefined;
27
+ quality?: "low" | "medium" | "high" | undefined;
28
+ thinking_level?: "minimal" | "high" | undefined;
29
+ reference_image_urls?: string[] | undefined;
26
30
  }, {
27
31
  confirm: true;
28
32
  prompt: string;
@@ -32,7 +36,9 @@ export declare const generateImageTool: {
32
36
  variations?: number | undefined;
33
37
  model?: "pro" | "lite" | "flash" | undefined;
34
38
  resolution?: "512" | "1K" | "2K" | "4K" | undefined;
35
- quality?: "low" | "medium" | undefined;
39
+ quality?: "low" | "medium" | "high" | undefined;
40
+ thinking_level?: "minimal" | "high" | undefined;
41
+ reference_image_urls?: string[] | undefined;
36
42
  }>;
37
43
  execute(client: PosterlyClient, input: {
38
44
  prompt: string;
@@ -42,7 +48,9 @@ export declare const generateImageTool: {
42
48
  provider?: "google" | "xai";
43
49
  model?: "lite" | "flash" | "pro";
44
50
  resolution?: "512" | "1K" | "2K" | "4K";
45
- quality?: "low" | "medium";
51
+ quality?: "low" | "medium" | "high";
52
+ thinking_level?: "minimal" | "high";
53
+ reference_image_urls?: string[];
46
54
  confirm: true;
47
55
  }): Promise<string>;
48
56
  };
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
- import { mdBullets, mdKeyValue, mdSection, mdTable, mdTitle } from '../lib/format.js';
2
+ import { mdKeyValue, mdTitle } from '../lib/format.js';
3
3
  export const generateImageTool = {
4
4
  name: 'generate_image',
5
- description: 'Generate an AI image via Posterly using Nano Banana (Gemini) or Grok Imagine Image 2.0 (xAI). The image is saved to the user\'s media storage and the returned URL can be passed to `create_post` as `media_url`.\n\n' +
6
- 'COSTS CREDITS. Every call consumes part of the user\'s monthly AI image quota (or purchased credits once the quota is exhausted). Do NOT call speculatively - always describe the image you\'re about to generate (subject, style, aspect ratio) to the user and get confirmation before calling.\n\n' +
5
+ description: 'Queue an AI image job via Posterly using Nano Banana (Gemini) or Grok Imagine Image 2.0 (xAI). Returns job_id. Poll get_image_job until status is completed, then pass urls to create_post as media_url / media_urls. Gemini thinking high does not change the credit price.\n\n' +
6
+ 'COSTS CREDITS. Every call consumes part of the user\'s monthly AI image quota (or purchased credits once the quota is exhausted). Do NOT call speculatively - always describe the image you\'re about to generate (subject, style, aspect ratio, quality/thinking, resolution) to the user and get confirmation before calling.\n\n' +
7
7
  'If the user is over their plan limit and has no credits, this tool returns a 402 with upgrade info. Surface that message verbatim - do not retry.\n\n' +
8
8
  'Common aspect ratios by platform:\n' +
9
9
  ' • Instagram feed / LinkedIn: 1:1 (square) or 4:5 (portrait)\n' +
@@ -50,10 +50,19 @@ export const generateImageTool = {
50
50
  .optional()
51
51
  .describe('Output resolution. Default 1K. xAI supports 1K/2K only. Google flash: 10/15/23/35 credits at 512/1K/2K/4K; pro: 30 at 1K-2K, 55 at 4K.'),
52
52
  quality: z
53
- .enum(['low', 'medium'])
53
+ .enum(['low', 'medium', 'high'])
54
54
  .optional()
55
- .describe('xAI only. Low costs 9/14 credits at 1K/2K; medium (default) costs 14/18 credits and gives better quality.'),
56
- confirm: z.literal(true).describe('Must be true after explicit user confirmation of subject, style, aspect ratio, and credit use.'),
55
+ .describe('Google: high turns on Gemini thinking (dashboard thinkingLevel=high). low/medium leave thinking minimal unless thinking_level is set. xAI: low or medium credit tiers; high is invalid.'),
56
+ thinking_level: z
57
+ .enum(['minimal', 'high'])
58
+ .optional()
59
+ .describe('Google flash/lite only. Gemini image quality control. minimal is fastest; high is for infographics, grounded scenes, and harder layouts. Pro reasons automatically. Overrides quality when both are set.'),
60
+ reference_image_urls: z
61
+ .array(z.string().url())
62
+ .max(14)
63
+ .optional()
64
+ .describe('Google only. Up to 14 HTTPS image URLs used as references (logo, product, style lock). Same as dashboard reference images.'),
65
+ confirm: z.literal(true).describe('Must be true after explicit user confirmation of subject, style, aspect ratio, quality, and credit use.'),
57
66
  }),
58
67
  async execute(client, input) {
59
68
  if (input.confirm !== true) {
@@ -62,20 +71,16 @@ export const generateImageTool = {
62
71
  const { confirm: _confirm, ...payload } = input;
63
72
  const result = await client.generateImage(payload);
64
73
  return [
65
- mdTitle(`✅ Generated ${result.images.length} image${result.images.length === 1 ? '' : 's'}`, `Model: ${result.model}`),
66
- mdTable(['#', 'Image URL', 'Filename'], result.images.map((img, index) => [
67
- index + 1,
68
- img.url,
69
- img.filename,
70
- ])),
74
+ mdTitle('Image job queued', `Job: ${result.job_id}`),
71
75
  mdKeyValue([
72
- ['Billed from', result.usage.billed_from],
76
+ ['Status', result.status],
77
+ ['Model', result.model],
78
+ ['Resolution', result.resolution],
79
+ ['Thinking', result.thinking_level || undefined],
73
80
  ['Credits used', result.credits_used],
74
- ['Plan usage', result.usage.limit != null ? `${result.usage.used ?? 0}/${result.usage.limit} this ${result.usage.period || 'period'}` : undefined],
75
- ['Plan tier', result.usage.tier || undefined],
81
+ ['Billed from', result.usage?.billed_from],
76
82
  ]),
77
- result.warnings?.length ? mdSection('Warnings', mdBullets(result.warnings)) : '',
78
- '**Next step:** Pass any URL above to `create_post` as `media_url`, or use multiple as `media_urls` for a carousel.',
83
+ result.message || 'Poll get_image_job with this job_id until status is completed, then pass urls to create_post.',
79
84
  ].filter(Boolean).join('\n\n');
80
85
  },
81
86
  };
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ import type { PosterlyClient } from '../lib/api-client.js';
3
+ export declare const getImageJobTool: {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: z.ZodObject<{
7
+ job_id: z.ZodOptional<z.ZodString>;
8
+ status: z.ZodOptional<z.ZodEnum<["pending", "processing", "completed", "failed"]>>;
9
+ limit: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ status?: "failed" | "pending" | "completed" | "processing" | undefined;
12
+ limit?: number | undefined;
13
+ job_id?: string | undefined;
14
+ }, {
15
+ status?: "failed" | "pending" | "completed" | "processing" | undefined;
16
+ limit?: number | undefined;
17
+ job_id?: string | undefined;
18
+ }>;
19
+ execute(client: PosterlyClient, input: {
20
+ job_id?: string;
21
+ status?: string;
22
+ limit?: number;
23
+ }): Promise<string>;
24
+ };
@@ -0,0 +1,31 @@
1
+ import { z } from 'zod';
2
+ export const getImageJobTool = {
3
+ name: 'get_image_job',
4
+ description: 'Get one AI image generation job by ID, or list recent image jobs when job_id is omitted. Use after generate_image to poll for completed urls.',
5
+ inputSchema: z.object({
6
+ job_id: z.string().optional(),
7
+ status: z.enum(['pending', 'processing', 'completed', 'failed']).optional(),
8
+ limit: z.number().int().min(1).max(50).default(10).optional(),
9
+ }),
10
+ async execute(client, input) {
11
+ const result = await client.getImageJob(input);
12
+ if (result.job)
13
+ return formatJob(result.job, true);
14
+ const jobs = result.jobs || [];
15
+ return [
16
+ `Image jobs (${jobs.length})`,
17
+ jobs.map((job) => formatJob(job, false)).join('\n\n'),
18
+ ].filter(Boolean).join('\n');
19
+ },
20
+ };
21
+ function formatJob(job, includeRaw) {
22
+ const lines = [
23
+ `${job.id}: ${job.status}`,
24
+ `Prompt: ${job.prompt}`,
25
+ `Model: ${job.model}; resolution: ${job.resolution}; thinking: ${job.thinking_level || 'n/a'}; cost: ${job.credit_cost}`,
26
+ job.urls?.length ? `URLs: ${job.urls.join(', ')}` : null,
27
+ job.error_message ? `Error: ${job.error_message}` : null,
28
+ includeRaw ? `\nRaw job:\n${JSON.stringify(job, null, 2)}` : null,
29
+ ];
30
+ return lines.filter(Boolean).join('\n');
31
+ }