codex-xai-oauth 0.1.0 → 0.2.2

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.
@@ -30948,7 +30948,7 @@ var StdioServerTransport = class {
30948
30948
  };
30949
30949
 
30950
30950
  // src/version.ts
30951
- var PACKAGE_VERSION = "0.1.0";
30951
+ var PACKAGE_VERSION = "0.2.2";
30952
30952
 
30953
30953
  // src/xai/constants.ts
30954
30954
  var XAI_BASE_URL = "https://api.x.ai/v1";
@@ -32241,7 +32241,7 @@ var Ky = class _Ky {
32241
32241
  }
32242
32242
  #getNormalizedOptions() {
32243
32243
  if (!this.#cachedNormalizedOptions) {
32244
- const { hooks, json: json2, parseJson, stringifyJson, searchParams, timeout: timeout2, totalTimeout, throwHttpErrors, fetch, ...normalizedOptions } = this.#options;
32244
+ const { hooks, json: json2, parseJson, stringifyJson, searchParams, timeout: timeout2, totalTimeout, throwHttpErrors, fetch: fetch2, ...normalizedOptions } = this.#options;
32245
32245
  this.#cachedNormalizedOptions = Object.freeze(normalizedOptions);
32246
32246
  }
32247
32247
  return this.#cachedNormalizedOptions;
@@ -32309,7 +32309,7 @@ function defaultAuthPath() {
32309
32309
  return join(configHome(), "codex-xai-oauth", "auth.json");
32310
32310
  }
32311
32311
  function authPath() {
32312
- return process.env["CODEX_XAI_OAUTH_AUTH_FILE"] || defaultAuthPath();
32312
+ return process.env["CODEX_XAI_OAUTH_AUTH_FILE"] || grokAuthPath();
32313
32313
  }
32314
32314
  function defaultGrokAuthPath() {
32315
32315
  return join(homedir(), ".grok", "auth.json");
@@ -32318,10 +32318,13 @@ function grokAuthPath() {
32318
32318
  return process.env["CODEX_XAI_OAUTH_GROK_AUTH_FILE"] || defaultGrokAuthPath();
32319
32319
  }
32320
32320
  function readStoredAuth(path = authPath()) {
32321
+ if (path === grokAuthPath()) {
32322
+ return readGrokStoredAuth(path) || (!process.env["CODEX_XAI_OAUTH_AUTH_FILE"] ? readPackageStoredAuth(defaultAuthPath()) : void 0);
32323
+ }
32324
+ return readPackageStoredAuth(path);
32325
+ }
32326
+ function readPackageStoredAuth(path) {
32321
32327
  if (!existsSync(path)) {
32322
- if (path === defaultAuthPath() && !process.env["CODEX_XAI_OAUTH_AUTH_FILE"]) {
32323
- return readGrokStoredAuth();
32324
- }
32325
32328
  return void 0;
32326
32329
  }
32327
32330
  try {
@@ -32350,6 +32353,9 @@ function readStoredAuth(path = authPath()) {
32350
32353
  throw error51;
32351
32354
  }
32352
32355
  }
32356
+ function grokEntryKey() {
32357
+ return `${XAI_OAUTH_ISSUER}::${XAI_OAUTH_CLIENT_ID}`;
32358
+ }
32353
32359
  function parseGrokExpiry(value) {
32354
32360
  const parsed = Date.parse(value);
32355
32361
  return Number.isNaN(parsed) ? void 0 : parsed;
@@ -32404,9 +32410,40 @@ function readGrokStoredAuth(path = grokAuthPath()) {
32404
32410
  }
32405
32411
  }
32406
32412
  function writeStoredAuth(auth, path = authPath()) {
32413
+ if (path === grokAuthPath()) {
32414
+ writeGrokStoredAuth(auth, path);
32415
+ return;
32416
+ }
32407
32417
  mkdirSync(dirname(path), { recursive: true, mode: 448 });
32408
32418
  writeFileSync(path, JSON.stringify(auth, null, 2), { mode: 384 });
32409
32419
  }
32420
+ function readGrokAuthFile(path) {
32421
+ if (!existsSync(path)) {
32422
+ return {};
32423
+ }
32424
+ try {
32425
+ const data = JSON.parse(readFileSync(path, "utf8"));
32426
+ return isRecord(data) ? data : {};
32427
+ } catch (error51) {
32428
+ if (error51 instanceof Error) {
32429
+ return {};
32430
+ }
32431
+ throw error51;
32432
+ }
32433
+ }
32434
+ function writeGrokStoredAuth(auth, path) {
32435
+ const data = readGrokAuthFile(path);
32436
+ data[grokEntryKey()] = {
32437
+ auth_mode: "oidc",
32438
+ expires_at: new Date(auth.expires).toISOString(),
32439
+ key: auth.access,
32440
+ oidc_client_id: XAI_OAUTH_CLIENT_ID,
32441
+ oidc_issuer: XAI_OAUTH_ISSUER,
32442
+ refresh_token: auth.refresh
32443
+ };
32444
+ mkdirSync(dirname(path), { recursive: true, mode: 448 });
32445
+ writeFileSync(path, JSON.stringify(data, null, 2), { mode: 384 });
32446
+ }
32410
32447
  function oauthExpiry(timestampSeconds) {
32411
32448
  return Date.now() + Number(timestampSeconds || 3600) * 1e3;
32412
32449
  }
@@ -32574,7 +32611,7 @@ async function resolveXaiCredentials() {
32574
32611
  };
32575
32612
  }
32576
32613
  throw new Error(
32577
- "xAI credentials not found. Run `codex-xai-oauth login --device`, set XAI_API_KEY, or configure a Codex model provider with experimental_bearer_token."
32614
+ "xAI credentials not found. Run `codex-xai-oauth login` to write ~/.grok/auth.json, run `codex-xai-oauth login --device`, set XAI_API_KEY, or configure a Codex model provider with experimental_bearer_token."
32578
32615
  );
32579
32616
  }
32580
32617
  async function credentialStatus() {
@@ -32623,6 +32660,80 @@ async function xaiRequest(path, options) {
32623
32660
  });
32624
32661
  }
32625
32662
 
32663
+ // src/xai/image-artifacts.ts
32664
+ import { mkdir, writeFile } from "node:fs/promises";
32665
+ import { join as join3 } from "node:path";
32666
+ async function artifactImageGenerationResult(result, options) {
32667
+ const artifacts = [];
32668
+ const images = result.data ?? [];
32669
+ for (let index = 0; index < images.length; index += 1) {
32670
+ const image = images[index];
32671
+ if (!image) {
32672
+ continue;
32673
+ }
32674
+ const artifact = await imageArtifactForPayload(image, index, options);
32675
+ if (artifact) {
32676
+ artifacts.push(artifact);
32677
+ }
32678
+ }
32679
+ return { ...result, artifacts };
32680
+ }
32681
+ async function imageArtifactForPayload(image, index, options) {
32682
+ if (image.b64_json) {
32683
+ const mimeType = image.mime_type ?? "image/png";
32684
+ const path = artifactPath(options.artifactDir, index, mimeType);
32685
+ await writeArtifact(path, Buffer.from(image.b64_json, "base64"));
32686
+ return {
32687
+ index,
32688
+ mime_type: mimeType,
32689
+ path,
32690
+ source: "base64",
32691
+ status: "saved"
32692
+ };
32693
+ }
32694
+ if (!image.url) {
32695
+ return void 0;
32696
+ }
32697
+ return downloadImageArtifact({ ...image, url: image.url }, index, options);
32698
+ }
32699
+ async function downloadImageArtifact(image, index, options) {
32700
+ try {
32701
+ const response = await (options.fetchImage ?? fetch)(image.url);
32702
+ if (!response.ok) {
32703
+ throw new Error(`download failed with status ${response.status}`);
32704
+ }
32705
+ const mimeType = image.mime_type ?? response.headers.get("content-type") ?? "image/png";
32706
+ const path = artifactPath(options.artifactDir, index, mimeType);
32707
+ await writeArtifact(path, Buffer.from(await response.arrayBuffer()));
32708
+ return {
32709
+ index,
32710
+ mime_type: mimeType,
32711
+ path,
32712
+ source: "url",
32713
+ status: "saved",
32714
+ url: image.url
32715
+ };
32716
+ } catch (error51) {
32717
+ return {
32718
+ error: error51 instanceof Error ? error51.message : String(error51),
32719
+ index,
32720
+ source: "url",
32721
+ status: "remote",
32722
+ url: image.url
32723
+ };
32724
+ }
32725
+ }
32726
+ async function writeArtifact(path, bytes) {
32727
+ await mkdir(join3(path, ".."), { recursive: true });
32728
+ await writeFile(path, bytes);
32729
+ }
32730
+ function artifactPath(artifactDir, index, mimeType) {
32731
+ return join3(artifactDir, `image-${index + 1}.${extensionForMime(mimeType)}`);
32732
+ }
32733
+ function extensionForMime(mimeType) {
32734
+ return mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
32735
+ }
32736
+
32626
32737
  // src/xai/media.ts
32627
32738
  async function xaiImageGenerate(args) {
32628
32739
  const body = {
@@ -32644,6 +32755,12 @@ async function xaiImageGenerate(args) {
32644
32755
  const parsed = await response.json();
32645
32756
  return isRecord(parsed) ? parsed : {};
32646
32757
  }
32758
+ async function xaiImageGenerateWithArtifacts(args) {
32759
+ const result = await xaiImageGenerate(args);
32760
+ return artifactImageGenerationResult(result, {
32761
+ artifactDir: args.artifactDir
32762
+ });
32763
+ }
32647
32764
  async function xaiTts(args) {
32648
32765
  const codec2 = args.codec || args.format;
32649
32766
  const body = {
@@ -32838,8 +32955,22 @@ function createXaiMcpServer() {
32838
32955
  async () => textJson({
32839
32956
  auth_file: authPath(),
32840
32957
  grok_auth_file: grokAuthPath(),
32958
+ legacy_auth_file: defaultAuthPath(),
32959
+ shared_auth_store: "~/.grok/auth.json",
32960
+ base_url: xaiBaseUrl(),
32961
+ browser_login: "codex-xai-oauth login",
32841
32962
  device_login: "codex-xai-oauth login --device",
32842
- api_key: "Set XAI_API_KEY in the environment."
32963
+ status: "codex-xai-oauth status",
32964
+ doctor: "codex-xai-oauth doctor",
32965
+ api_key: "Set XAI_API_KEY in the environment.",
32966
+ credential_precedence: [
32967
+ "CODEX_XAI_OAUTH_AUTH_FILE",
32968
+ "~/.grok/auth.json",
32969
+ "~/.config/codex-xai-oauth/auth.json",
32970
+ "XAI_API_KEY",
32971
+ "Codex model provider experimental_bearer_token"
32972
+ ],
32973
+ note: "Default OAuth login writes a shared xAI OIDC entry to ~/.grok/auth.json; this is a shared auth store, not a requirement to use a specific Grok CLI build."
32843
32974
  })
32844
32975
  );
32845
32976
  registerGenerationTools(server);
@@ -32897,19 +33028,34 @@ function registerMediaTools(server) {
32897
33028
  n: external_exports.number().int().min(1).max(10).optional(),
32898
33029
  resolution: external_exports.enum(["1k", "2k"]).optional(),
32899
33030
  response_format: external_exports.enum(["url", "b64_json"]).optional(),
32900
- size: external_exports.string().optional()
33031
+ size: external_exports.string().optional(),
33032
+ artifact_dir: external_exports.string().optional()
32901
33033
  })
32902
33034
  },
32903
- async ({ prompt, model, n, resolution, response_format, size }) => textJson(
32904
- await xaiImageGenerate({
33035
+ async ({
33036
+ prompt,
33037
+ model,
33038
+ n,
33039
+ resolution,
33040
+ response_format,
33041
+ size,
33042
+ artifact_dir
33043
+ }) => {
33044
+ const args = {
32905
33045
  prompt,
32906
33046
  ...model ? { model } : {},
32907
33047
  ...n ? { n } : {},
32908
33048
  ...resolution ? { resolution } : {},
32909
33049
  ...response_format ? { response_format } : {},
32910
33050
  ...size ? { size } : {}
32911
- })
32912
- )
33051
+ };
33052
+ return textJson(
33053
+ artifact_dir ? await xaiImageGenerateWithArtifacts({
33054
+ ...args,
33055
+ artifactDir: artifact_dir
33056
+ }) : await xaiImageGenerate(args)
33057
+ );
33058
+ }
32913
33059
  );
32914
33060
  server.registerTool(
32915
33061
  "xai_tts",
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const PACKAGE_VERSION = "0.1.0";
1
+ export declare const PACKAGE_VERSION = "0.2.2";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -12,6 +12,6 @@ export declare const XAI_REDIRECT_PATH = "/callback";
12
12
  export declare const OPENAI_COMPAT_HOST = "127.0.0.1";
13
13
  export declare const OPENAI_COMPAT_PORT = 8787;
14
14
  export declare const REFRESH_SKEW_MS: number;
15
- export declare const USER_AGENT = "codex-xai-oauth/0.1.0";
15
+ export declare const USER_AGENT = "codex-xai-oauth/0.2.2";
16
16
  export declare function xaiBaseUrl(): string;
17
17
  //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1,33 @@
1
+ export type ImagePayload = {
2
+ readonly b64_json?: string;
3
+ readonly mime_type?: string;
4
+ readonly url?: string;
5
+ };
6
+ export type ImageGenerationWithData = {
7
+ readonly data?: readonly ImagePayload[];
8
+ readonly [key: string]: unknown;
9
+ };
10
+ export type SavedImageArtifact = {
11
+ readonly index: number;
12
+ readonly mime_type: string;
13
+ readonly path: string;
14
+ readonly source: "base64" | "url";
15
+ readonly status: "saved";
16
+ readonly url?: string;
17
+ };
18
+ export type RemoteImageArtifact = {
19
+ readonly error: string;
20
+ readonly index: number;
21
+ readonly source: "url";
22
+ readonly status: "remote";
23
+ readonly url: string;
24
+ };
25
+ export type ImageArtifact = SavedImageArtifact | RemoteImageArtifact;
26
+ export type ImageArtifactGenerationResult = ImageGenerationWithData & {
27
+ readonly artifacts: readonly ImageArtifact[];
28
+ };
29
+ export declare function artifactImageGenerationResult(result: ImageGenerationWithData, options: {
30
+ readonly artifactDir: string;
31
+ readonly fetchImage?: (url: string) => Promise<Response>;
32
+ }): Promise<ImageArtifactGenerationResult>;
33
+ //# sourceMappingURL=image-artifacts.d.ts.map
@@ -1,7 +1,7 @@
1
1
  export { beginOAuth, startCallbackServer } from "./browser-oauth.js";
2
2
  export { credentialStatus, resolveXaiCredentials } from "./credentials.js";
3
3
  export { beginDeviceOAuth, pollDeviceToken, requestDeviceCode, } from "./device-oauth.js";
4
- export { xaiImageGenerate, xaiTts, xaiVideoGenerate } from "./media.js";
4
+ export { xaiImageGenerate, xaiImageGenerateWithArtifacts, xaiTts, xaiVideoGenerate, } from "./media.js";
5
5
  export { buildAuthorizeUrl, discoverXaiOAuth, exchangeCodeForToken, pkcePair, refreshAccessToken, storedAuthFromToken, } from "./oauth.js";
6
6
  export { xaiChatCompletions, xaiResponses } from "./responses.js";
7
7
  export { authPath, defaultAuthPath, defaultGrokAuthPath, grokAuthPath, readGrokStoredAuth, readStoredAuth, writeStoredAuth, } from "./storage.js";
@@ -1,3 +1,4 @@
1
+ import { type ImageArtifactGenerationResult } from "./image-artifacts.js";
1
2
  export declare function xaiImageGenerate(args: {
2
3
  readonly model?: string;
3
4
  readonly n?: number;
@@ -6,6 +7,15 @@ export declare function xaiImageGenerate(args: {
6
7
  readonly response_format?: "url" | "b64_json";
7
8
  readonly size?: string;
8
9
  }): Promise<Record<string, unknown>>;
10
+ export declare function xaiImageGenerateWithArtifacts(args: {
11
+ readonly artifactDir: string;
12
+ readonly model?: string;
13
+ readonly n?: number;
14
+ readonly prompt: string;
15
+ readonly resolution?: "1k" | "2k";
16
+ readonly response_format?: "url" | "b64_json";
17
+ readonly size?: string;
18
+ }): Promise<ImageArtifactGenerationResult>;
9
19
  export declare function xaiTts(args: {
10
20
  readonly bit_rate?: number;
11
21
  readonly codec?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-xai-oauth",
3
- "version": "0.1.0",
3
+ "version": "0.2.2",
4
4
  "description": "Codex plugin exposing xAI/Grok OAuth and API-key tools through a local MCP server.",
5
5
  "type": "module",
6
6
  "main": "./dist/mcp/server.js",
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: xai_generate_text
3
+ description: Use when the user asks to generate, draft, answer, rewrite, summarize, or reason with xAI/Grok text generation through xai_generate_text.
4
+ ---
5
+
6
+ # xAI Generate Text
7
+
8
+ Use `xai_generate_text` for text generation with Grok through xAI Responses.
9
+
10
+ Preferred MCP call:
11
+
12
+ ```json
13
+ {
14
+ "prompt": "Write a concise release note for artifact-backed image generation.",
15
+ "reasoning_effort": "medium"
16
+ }
17
+ ```
18
+
19
+ Options:
20
+
21
+ - `prompt`: required user request.
22
+ - `model`: optional Grok model.
23
+ - `reasoning_effort`: `low`, `medium`, or `high`.
24
+
25
+ Use `xai_web_search` instead when the user asks for current web information. Use `xai_x_search` instead when the user asks to search X/Twitter.
@@ -1,11 +1,20 @@
1
1
  ---
2
2
  name: xai-grok
3
- description: Use xAI/Grok OAuth or API-key MCP tools for text generation, web search, X search, image generation, TTS, video generation, or credential status from Codex.
3
+ description: Use only for general codex-xai-oauth/xAI Grok plugin overview, setup orientation, or multi-tool requests when no dedicated xai_* skill is a better fit.
4
4
  ---
5
5
 
6
6
  # xAI Grok
7
7
 
8
- Use the bundled MCP tools when the user asks for xAI, Grok, Grok Imagine, xAI image generation, xAI web search, X search, TTS, video generation, or xAI credential status.
8
+ Use this umbrella skill only for general plugin overview, setup orientation, or multi-tool xAI/Grok requests. For a specific tool request, prefer the dedicated skill:
9
+
10
+ - `xai_status`
11
+ - `xai_login_instructions`
12
+ - `xai_generate_text`
13
+ - `xai_web_search`
14
+ - `xai_x_search`
15
+ - `xai_image_generate`
16
+ - `xai_tts`
17
+ - `xai_video_generate`
9
18
 
10
19
  ## Tools
11
20
 
@@ -14,16 +23,16 @@ Use the bundled MCP tools when the user asks for xAI, Grok, Grok Imagine, xAI im
14
23
  - `xai_generate_text`: generate text with Grok through xAI Responses.
15
24
  - `xai_web_search`: answer with xAI server-side web search.
16
25
  - `xai_x_search`: answer with xAI server-side X search. Do not pass both allowed and excluded handles.
17
- - `xai_image_generate`: generate images with xAI `/images/generations`.
26
+ - `xai_image_generate`: generate images with xAI `/images/generations`. Pass `artifact_dir` when the user wants local files; URL and `b64_json` images are saved there and returned in `artifacts`.
18
27
  - `xai_tts`: generate speech audio.
19
28
  - `xai_video_generate`: generate video.
20
29
 
21
30
  ## Credential Rules
22
31
 
23
- - Prefer existing OAuth credentials in `~/.config/codex-xai-oauth/auth.json`.
24
- - If package OAuth credentials are absent, use the Grok CLI OIDC session in `~/.grok/auth.json`.
25
- - `CODEX_XAI_OAUTH_AUTH_FILE` overrides the auth-file path.
26
- - `CODEX_XAI_OAUTH_GROK_AUTH_FILE` overrides the Grok CLI auth-file path.
32
+ - Prefer the shared xAI OIDC auth store at `~/.grok/auth.json`. It is a shared auth file, not a requirement to use a specific Grok CLI build.
33
+ - `CODEX_XAI_OAUTH_AUTH_FILE` overrides the auth-file path with a package-format OAuth file.
34
+ - `CODEX_XAI_OAUTH_GROK_AUTH_FILE` overrides the shared xAI OIDC auth-file path.
35
+ - Legacy package OAuth credentials at `~/.config/codex-xai-oauth/auth.json` are read only when the shared store is absent.
27
36
  - `XAI_API_KEY` is the fallback credential.
28
37
  - `XAI_BASE_URL` can override the API base URL.
29
38
  - Do not print, quote, summarize, or store access tokens, refresh tokens, or API keys in chat.
@@ -47,3 +56,46 @@ To check status:
47
56
  ```bash
48
57
  codex-xai-oauth status
49
58
  ```
59
+
60
+ ## Image Generation
61
+
62
+ Use `xai_image_generate` when the user asks to generate an image, Grok Imagine image, or xAI image. Defaults are `model: grok-imagine-image`, `response_format: url`, and `n: 1`.
63
+
64
+ Preferred MCP call:
65
+
66
+ ```json
67
+ {
68
+ "prompt": "tiny minimalist blue dot icon on white background",
69
+ "resolution": "2k",
70
+ "artifact_dir": ".codex-xai-artifacts"
71
+ }
72
+ ```
73
+
74
+ Direct CLI equivalent:
75
+
76
+ ```bash
77
+ codex-xai-oauth image \
78
+ --prompt "tiny minimalist blue dot icon on white background" \
79
+ --resolution 2k \
80
+ --artifact-dir .codex-xai-artifacts
81
+ ```
82
+
83
+ For base64 image payloads saved locally:
84
+
85
+ ```bash
86
+ codex-xai-oauth image \
87
+ --prompt "a cinematic robot reading a book" \
88
+ --response-format b64_json \
89
+ --artifact-dir .codex-xai-artifacts
90
+ ```
91
+
92
+ Supported image options:
93
+
94
+ - `prompt`: required image prompt.
95
+ - `n`: number of images.
96
+ - `resolution`: `1k` or `2k`.
97
+ - `response_format`: `url` or `b64_json`.
98
+ - `size`: provider-specific size string.
99
+ - `artifact_dir`: local directory for saved image artifacts.
100
+
101
+ When `artifact_dir` is provided, return both the upstream JSON and the `artifacts` metadata. Each saved artifact includes a local `path`, `mime_type`, `source`, and `status`. If a remote URL cannot be downloaded, preserve the upstream `url` with `status: remote` instead of hiding it.
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: xai_image_generate
3
+ description: Use when the user asks to generate, create, make, or save images with xAI, Grok Imagine, xai_image_generate, or codex-xai-oauth image artifacts.
4
+ ---
5
+
6
+ # xAI Image Generate
7
+
8
+ Use `xai_image_generate` for xAI/Grok Imagine image requests.
9
+
10
+ ## Preferred MCP Call
11
+
12
+ ```json
13
+ {
14
+ "prompt": "tiny minimalist blue dot icon on white background",
15
+ "resolution": "2k",
16
+ "artifact_dir": ".codex-xai-artifacts"
17
+ }
18
+ ```
19
+
20
+ ## CLI Equivalent
21
+
22
+ ```bash
23
+ codex-xai-oauth image \
24
+ --prompt "tiny minimalist blue dot icon on white background" \
25
+ --resolution 2k \
26
+ --artifact-dir .codex-xai-artifacts
27
+ ```
28
+
29
+ For base64 image payloads saved locally:
30
+
31
+ ```bash
32
+ codex-xai-oauth image \
33
+ --prompt "a cinematic robot reading a book" \
34
+ --response-format b64_json \
35
+ --artifact-dir .codex-xai-artifacts
36
+ ```
37
+
38
+ ## Options
39
+
40
+ - `prompt`: required image prompt.
41
+ - `model`: defaults to `grok-imagine-image`.
42
+ - `n`: number of images.
43
+ - `resolution`: `1k` or `2k`.
44
+ - `response_format`: `url` or `b64_json`.
45
+ - `size`: provider-specific size string.
46
+ - `artifact_dir`: local directory for saved image artifacts.
47
+
48
+ When `artifact_dir` is present, return the upstream JSON plus `artifacts`. Saved artifacts include `path`, `mime_type`, `source`, and `status`. If a remote URL cannot be downloaded, preserve its upstream `url` with `status: remote`.
49
+
50
+ ## Credential Safety
51
+
52
+ Use existing credentials. If credentials are missing, ask the user to run:
53
+
54
+ ```bash
55
+ codex-xai-oauth login --device
56
+ ```
57
+
58
+ or set `XAI_API_KEY`. Never print or expose OAuth tokens or API keys.
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: xai_login_instructions
3
+ description: Use when the user asks how to log in, authenticate, configure OAuth, set up XAI_API_KEY, or fix missing xAI/Grok credentials for codex-xai-oauth.
4
+ ---
5
+
6
+ # xAI Login Instructions
7
+
8
+ Use `xai_login_instructions` when the user needs setup commands or auth-file paths.
9
+
10
+ Default OAuth login writes a shared xAI OIDC entry to `~/.grok/auth.json`. This is a shared auth store, not a requirement to use a specific Grok CLI build.
11
+
12
+ For browser login:
13
+
14
+ ```bash
15
+ codex-xai-oauth login
16
+ ```
17
+
18
+ For OAuth device login:
19
+
20
+ ```bash
21
+ codex-xai-oauth login --device
22
+ ```
23
+
24
+ For API-key fallback:
25
+
26
+ ```bash
27
+ export XAI_API_KEY=xai-...
28
+ ```
29
+
30
+ Credential safety:
31
+
32
+ - Do not expose token material.
33
+ - Prefer `~/.grok/auth.json` unless `CODEX_XAI_OAUTH_AUTH_FILE` is explicitly set.
34
+ - Treat `~/.config/codex-xai-oauth/auth.json` as a legacy fallback.
35
+ - Mention `XAI_API_KEY` only as an environment variable name, never as a value.
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: xai_status
3
+ description: Use when the user asks to check xAI, Grok, codex-xai-oauth, OAuth, API-key, or credential status without exposing secrets.
4
+ ---
5
+
6
+ # xAI Status
7
+
8
+ Use `xai_status` to check whether xAI credentials are available.
9
+
10
+ Return a concise status summary. Never print, quote, or expose OAuth tokens, refresh tokens, bearer tokens, or API keys.
11
+
12
+ CLI equivalent:
13
+
14
+ ```bash
15
+ codex-xai-oauth status
16
+ ```
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: xai_tts
3
+ description: Use when the user asks to generate speech, text-to-speech, audio narration, voice output, or TTS with xAI/Grok through xai_tts.
4
+ ---
5
+
6
+ # xAI TTS
7
+
8
+ Use `xai_tts` to generate speech audio.
9
+
10
+ Preferred MCP call:
11
+
12
+ ```json
13
+ {
14
+ "input": "Hello from Grok.",
15
+ "voice_id": "eve",
16
+ "language": "auto",
17
+ "codec": "mp3"
18
+ }
19
+ ```
20
+
21
+ Options:
22
+
23
+ - `input`: required text to speak.
24
+ - `voice_id`: optional voice, default `eve`.
25
+ - `language`: optional language, default `auto`.
26
+ - `codec`: optional output codec.
27
+
28
+ Return the content type and explain that the audio bytes are returned as base64 in the tool output.
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: xai_video_generate
3
+ description: Use when the user asks to generate video, Grok Imagine video, text-to-video, image-to-video, or xAI video through xai_video_generate.
4
+ ---
5
+
6
+ # xAI Video Generate
7
+
8
+ Use `xai_video_generate` for Grok Imagine video generation.
9
+
10
+ Preferred text-to-video MCP call:
11
+
12
+ ```json
13
+ {
14
+ "prompt": "A serene mountain lake at sunrise with slow camera pan, cinematic lighting"
15
+ }
16
+ ```
17
+
18
+ Image-to-video MCP call:
19
+
20
+ ```json
21
+ {
22
+ "prompt": "Animate this image with a slow camera push-in",
23
+ "image_url": "https://example.com/start-frame.jpg"
24
+ }
25
+ ```
26
+
27
+ Reference-image MCP call:
28
+
29
+ ```json
30
+ {
31
+ "prompt": "Create a short cinematic shot using these reference images for style consistency",
32
+ "reference_image_urls": [
33
+ "https://example.com/reference-1.jpg",
34
+ "https://example.com/reference-2.jpg"
35
+ ]
36
+ }
37
+ ```
38
+
39
+ Options:
40
+
41
+ - `prompt`: required video prompt.
42
+ - `image_url`: optional starting image for image-to-video.
43
+ - `reference_image_urls`: optional array of up to 7 reference images.
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: xai_web_search
3
+ description: Use when the user asks xAI/Grok to search the web, find current information, answer with citations, or use server-side web_search.
4
+ ---
5
+
6
+ # xAI Web Search
7
+
8
+ Use `xai_web_search` for web-backed answers through xAI Responses server-side `web_search`.
9
+
10
+ Preferred MCP call:
11
+
12
+ ```json
13
+ {
14
+ "prompt": "Find the latest xAI model announcement and summarize it with citations."
15
+ }
16
+ ```
17
+
18
+ Options:
19
+
20
+ - `prompt`: required search question.
21
+ - `model`: optional Grok model.
22
+
23
+ Return a concise answer and include citations from the tool output when available.