@fre4x/grok 1.0.46 → 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.
- package/README.md +6 -0
- package/dist/index.js +148 -8
- package/package.json +2 -2
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
|
@@ -18436,7 +18436,8 @@ var require_follow_redirects = __commonJS({
|
|
|
18436
18436
|
});
|
|
18437
18437
|
|
|
18438
18438
|
// src/index.ts
|
|
18439
|
-
import {
|
|
18439
|
+
import { realpathSync } from "node:fs";
|
|
18440
|
+
import { fileURLToPath } from "node:url";
|
|
18440
18441
|
|
|
18441
18442
|
// ../packages/shared/dist/errors.js
|
|
18442
18443
|
function createApiError(message, statusCode) {
|
|
@@ -43634,6 +43635,16 @@ var z3 = external_exports || zod_default || zod_exports;
|
|
|
43634
43635
|
var XAI_API_KEY = process.env.XAI_API_KEY;
|
|
43635
43636
|
var aspectRatioValues = ["1:1", "16:9", "9:16"];
|
|
43636
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==";
|
|
43637
43648
|
var xSearchSchema = paginationSchema.extend({
|
|
43638
43649
|
query: z3.string().min(1).max(500),
|
|
43639
43650
|
allowed_handles: z3.array(z3.string().min(1).max(50)).max(10).optional(),
|
|
@@ -43984,6 +43995,97 @@ function asArray(value) {
|
|
|
43984
43995
|
function asString(value) {
|
|
43985
43996
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
43986
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
|
+
}
|
|
43987
44089
|
function extractNestedText(value) {
|
|
43988
44090
|
if (typeof value === "string") {
|
|
43989
44091
|
return value.trim() ? [value.trim()] : [];
|
|
@@ -44215,9 +44317,12 @@ function parseArguments(toolName, schema, args) {
|
|
|
44215
44317
|
}
|
|
44216
44318
|
return { data: parsed.data };
|
|
44217
44319
|
}
|
|
44218
|
-
function toolResult(text, structuredContent) {
|
|
44320
|
+
function toolResult(text, structuredContent, extraContent = []) {
|
|
44219
44321
|
return {
|
|
44220
|
-
content: [
|
|
44322
|
+
content: [
|
|
44323
|
+
{ type: "text", text },
|
|
44324
|
+
...extraContent
|
|
44325
|
+
],
|
|
44221
44326
|
structuredContent
|
|
44222
44327
|
};
|
|
44223
44328
|
}
|
|
@@ -44370,7 +44475,14 @@ async function handleToolCall(name, args, client = xaiClient) {
|
|
|
44370
44475
|
prompt,
|
|
44371
44476
|
aspect_ratio
|
|
44372
44477
|
);
|
|
44373
|
-
|
|
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);
|
|
44374
44486
|
}
|
|
44375
44487
|
case "grok_animate": {
|
|
44376
44488
|
const parsed = parseArguments(name, animateSchema, args);
|
|
@@ -44390,7 +44502,16 @@ async function handleToolCall(name, args, client = xaiClient) {
|
|
|
44390
44502
|
aspect_ratio,
|
|
44391
44503
|
image_url
|
|
44392
44504
|
);
|
|
44393
|
-
|
|
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
|
+
);
|
|
44394
44515
|
}
|
|
44395
44516
|
case "grok_check_video_status": {
|
|
44396
44517
|
const parsed = parseArguments(name, videoStatusSchema, args);
|
|
@@ -44400,7 +44521,16 @@ async function handleToolCall(name, args, client = xaiClient) {
|
|
|
44400
44521
|
const { request_id } = parsed.data;
|
|
44401
44522
|
const rawResponse = IS_MOCK ? MOCK_FIXTURES.grok_check_video_status : (await client.get(`/videos/status/${request_id}`)).data;
|
|
44402
44523
|
const output = normalizeVideoStatusResponse(rawResponse);
|
|
44403
|
-
|
|
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
|
+
);
|
|
44404
44534
|
}
|
|
44405
44535
|
default:
|
|
44406
44536
|
throw new McpError(
|
|
@@ -44431,8 +44561,18 @@ async function runServer() {
|
|
|
44431
44561
|
await server.connect(transport);
|
|
44432
44562
|
console.error("Grok MCP Server running on stdio");
|
|
44433
44563
|
}
|
|
44434
|
-
|
|
44435
|
-
if (
|
|
44564
|
+
function isMainModule(url3) {
|
|
44565
|
+
if (!process.argv[1]) return false;
|
|
44566
|
+
try {
|
|
44567
|
+
const scriptPath = fileURLToPath(url3);
|
|
44568
|
+
const realScriptPath = realpathSync(scriptPath);
|
|
44569
|
+
const realArgvPath = realpathSync(process.argv[1]);
|
|
44570
|
+
return realScriptPath === realArgvPath;
|
|
44571
|
+
} catch {
|
|
44572
|
+
return false;
|
|
44573
|
+
}
|
|
44574
|
+
}
|
|
44575
|
+
if (isMainModule(import.meta.url)) {
|
|
44436
44576
|
runServer().catch((error48) => {
|
|
44437
44577
|
console.error("Fatal error running server:", error48);
|
|
44438
44578
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fre4x/grok",
|
|
3
|
-
"version": "1.0.
|
|
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",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"start": "node dist/index.js",
|
|
17
17
|
"dev": "tsx src/index.ts",
|
|
18
18
|
"watch": "tsc -w",
|
|
19
|
-
"inspector": "
|
|
19
|
+
"inspector": "node ../scripts/run-official-inspector.mjs node dist/index.js",
|
|
20
20
|
"prepublishOnly": "npm run build && npm run typecheck",
|
|
21
21
|
"test": "vitest run --passWithNoTests --exclude dist"
|
|
22
22
|
},
|