@fre4x/grok 1.0.47 → 1.0.49

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 (3) hide show
  1. package/README.md +6 -0
  2. package/dist/index.js +134 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -18,6 +18,8 @@ xAI's Grok is more than an LLM. It's a real-time sensor for the global conscious
18
18
 
19
19
  Search tools support `limit` and `offset` pagination and return normalized results with citations.
20
20
 
21
+ Image generation responses include direct MCP `image` content blocks when media can be embedded. Video responses include direct MCP embedded `resource` blobs because MCP does not define a dedicated `video` content block.
22
+
21
23
  ## Configuration
22
24
 
23
25
  Required environment variable:
@@ -29,6 +31,10 @@ Mock mode is supported for local development and offline validation:
29
31
  MOCK=true npx @fre4x/grok
30
32
  ```
31
33
 
34
+ Optional media embedding controls:
35
+ - `GROK_MAX_EMBEDDED_MEDIA_BYTES`: Maximum bytes to inline into MCP `content` blocks. Defaults to `5242880`.
36
+ - `GROK_MEDIA_FETCH_TIMEOUT_MS`: Timeout for downloading generated media before embedding. Defaults to `15000`.
37
+
32
38
  ## Deploy
33
39
 
34
40
  ```json
package/dist/index.js CHANGED
@@ -43635,6 +43635,16 @@ var z3 = external_exports || zod_default || zod_exports;
43635
43635
  var XAI_API_KEY = process.env.XAI_API_KEY;
43636
43636
  var aspectRatioValues = ["1:1", "16:9", "9:16"];
43637
43637
  var MAX_SEARCH_RESULTS = 100;
43638
+ var MAX_EMBEDDED_MEDIA_BYTES = Number.parseInt(
43639
+ process.env.GROK_MAX_EMBEDDED_MEDIA_BYTES || "5242880",
43640
+ 10
43641
+ );
43642
+ var MEDIA_FETCH_TIMEOUT_MS = Number.parseInt(
43643
+ process.env.GROK_MEDIA_FETCH_TIMEOUT_MS || "15000",
43644
+ 10
43645
+ );
43646
+ var MOCK_IMAGE_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==";
43647
+ var MOCK_VIDEO_BASE64 = "AAAAHGZ0eXBpc29tAAAAAGlzb21pc28yYXZjMQ==";
43638
43648
  var xSearchSchema = paginationSchema.extend({
43639
43649
  query: z3.string().min(1).max(500),
43640
43650
  allowed_handles: z3.array(z3.string().min(1).max(50)).max(10).optional(),
@@ -43985,6 +43995,97 @@ function asArray(value) {
43985
43995
  function asString(value) {
43986
43996
  return typeof value === "string" && value.trim() ? value : void 0;
43987
43997
  }
43998
+ function inferMimeTypeFromUrl(url3, kind) {
43999
+ try {
44000
+ const pathname = new URL(url3).pathname.toLowerCase();
44001
+ if (pathname.endsWith(".png")) return "image/png";
44002
+ if (pathname.endsWith(".jpg") || pathname.endsWith(".jpeg")) {
44003
+ return "image/jpeg";
44004
+ }
44005
+ if (pathname.endsWith(".webp")) return "image/webp";
44006
+ if (pathname.endsWith(".gif")) return "image/gif";
44007
+ if (pathname.endsWith(".mp4")) return "video/mp4";
44008
+ if (pathname.endsWith(".webm")) return "video/webm";
44009
+ if (pathname.endsWith(".mov")) return "video/quicktime";
44010
+ } catch {
44011
+ }
44012
+ return kind === "image" ? "image/png" : "video/mp4";
44013
+ }
44014
+ function normalizeMediaMimeType(value, kind, sourceUrl) {
44015
+ if (typeof value === "string") {
44016
+ const trimmed = value.split(";", 1)[0]?.trim().toLowerCase();
44017
+ if (trimmed && (kind === "image" && trimmed.startsWith("image/") || kind === "video" && trimmed.startsWith("video/"))) {
44018
+ return trimmed;
44019
+ }
44020
+ }
44021
+ return inferMimeTypeFromUrl(sourceUrl, kind) || "application/octet-stream";
44022
+ }
44023
+ async function fetchMediaAsBase64(sourceUrl, kind, client = axios_default) {
44024
+ try {
44025
+ const response = await client.get(sourceUrl, {
44026
+ responseType: "arraybuffer",
44027
+ timeout: MEDIA_FETCH_TIMEOUT_MS,
44028
+ maxContentLength: MAX_EMBEDDED_MEDIA_BYTES,
44029
+ maxBodyLength: MAX_EMBEDDED_MEDIA_BYTES
44030
+ });
44031
+ const buffer = Buffer.from(response.data);
44032
+ if (buffer.byteLength === 0 || buffer.byteLength > MAX_EMBEDDED_MEDIA_BYTES) {
44033
+ return void 0;
44034
+ }
44035
+ return {
44036
+ data: buffer.toString("base64"),
44037
+ mimeType: normalizeMediaMimeType(
44038
+ response.headers["content-type"],
44039
+ kind,
44040
+ sourceUrl
44041
+ )
44042
+ };
44043
+ } catch {
44044
+ return void 0;
44045
+ }
44046
+ }
44047
+ async function buildImageContent(imageUrl, client = axios_default) {
44048
+ const media = await fetchMediaAsBase64(imageUrl, "image", client);
44049
+ if (!media) {
44050
+ return void 0;
44051
+ }
44052
+ return {
44053
+ type: "image",
44054
+ data: media.data,
44055
+ mimeType: media.mimeType
44056
+ };
44057
+ }
44058
+ async function buildVideoContent(videoUrl, client = axios_default) {
44059
+ const media = await fetchMediaAsBase64(videoUrl, "video", client);
44060
+ if (!media) {
44061
+ return void 0;
44062
+ }
44063
+ return {
44064
+ type: "resource",
44065
+ resource: {
44066
+ uri: videoUrl,
44067
+ mimeType: media.mimeType,
44068
+ blob: media.data
44069
+ }
44070
+ };
44071
+ }
44072
+ function buildMockImageContent() {
44073
+ return {
44074
+ type: "image",
44075
+ data: MOCK_IMAGE_BASE64,
44076
+ mimeType: "image/png"
44077
+ };
44078
+ }
44079
+ function buildMockVideoContent(videoUrl) {
44080
+ return {
44081
+ type: "resource",
44082
+ resource: {
44083
+ uri: videoUrl,
44084
+ mimeType: "video/mp4",
44085
+ blob: MOCK_VIDEO_BASE64
44086
+ }
44087
+ };
44088
+ }
43988
44089
  function extractNestedText(value) {
43989
44090
  if (typeof value === "string") {
43990
44091
  return value.trim() ? [value.trim()] : [];
@@ -44216,9 +44317,12 @@ function parseArguments(toolName, schema, args) {
44216
44317
  }
44217
44318
  return { data: parsed.data };
44218
44319
  }
44219
- function toolResult(text, structuredContent) {
44320
+ function toolResult(text, structuredContent, extraContent = []) {
44220
44321
  return {
44221
- content: [{ type: "text", text }],
44322
+ content: [
44323
+ { type: "text", text },
44324
+ ...extraContent
44325
+ ],
44222
44326
  structuredContent
44223
44327
  };
44224
44328
  }
@@ -44371,7 +44475,14 @@ async function handleToolCall(name, args, client = xaiClient) {
44371
44475
  prompt,
44372
44476
  aspect_ratio
44373
44477
  );
44374
- return toolResult(renderImagine(output), output);
44478
+ const mediaContent = IS_MOCK ? [buildMockImageContent()] : (await Promise.all(
44479
+ output.images.map(
44480
+ (image) => buildImageContent(image.url)
44481
+ )
44482
+ )).filter(
44483
+ (item) => item !== void 0
44484
+ );
44485
+ return toolResult(renderImagine(output), output, mediaContent);
44375
44486
  }
44376
44487
  case "grok_animate": {
44377
44488
  const parsed = parseArguments(name, animateSchema, args);
@@ -44391,7 +44502,16 @@ async function handleToolCall(name, args, client = xaiClient) {
44391
44502
  aspect_ratio,
44392
44503
  image_url
44393
44504
  );
44394
- return toolResult(renderVideoGeneration(output), output);
44505
+ const mediaContent = output.video_url === void 0 ? [] : IS_MOCK ? [buildMockVideoContent(output.video_url)] : (await Promise.all([
44506
+ buildVideoContent(output.video_url)
44507
+ ])).filter(
44508
+ (item) => item !== void 0
44509
+ );
44510
+ return toolResult(
44511
+ renderVideoGeneration(output),
44512
+ output,
44513
+ mediaContent
44514
+ );
44395
44515
  }
44396
44516
  case "grok_check_video_status": {
44397
44517
  const parsed = parseArguments(name, videoStatusSchema, args);
@@ -44401,7 +44521,16 @@ async function handleToolCall(name, args, client = xaiClient) {
44401
44521
  const { request_id } = parsed.data;
44402
44522
  const rawResponse = IS_MOCK ? MOCK_FIXTURES.grok_check_video_status : (await client.get(`/videos/status/${request_id}`)).data;
44403
44523
  const output = normalizeVideoStatusResponse(rawResponse);
44404
- return toolResult(renderVideoStatus(output), output);
44524
+ const mediaContent = output.video_url === void 0 ? [] : IS_MOCK ? [buildMockVideoContent(output.video_url)] : (await Promise.all([
44525
+ buildVideoContent(output.video_url)
44526
+ ])).filter(
44527
+ (item) => item !== void 0
44528
+ );
44529
+ return toolResult(
44530
+ renderVideoStatus(output),
44531
+ output,
44532
+ mediaContent
44533
+ );
44405
44534
  }
44406
44535
  default:
44407
44536
  throw new McpError(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fre4x/grok",
3
- "version": "1.0.47",
3
+ "version": "1.0.49",
4
4
  "description": "An MCP server for xAI (Grok) with search and generation capabilities.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",