@blockrun/mcp 0.6.9 → 0.7.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 (2) hide show
  1. package/dist/index.js +188 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -105,10 +105,11 @@ var MODEL_TIERS = {
105
105
  fast: ["google/gemini-2.5-flash", "google/gemini-3.1-flash-lite", "openai/gpt-5-mini", "deepseek/deepseek-chat", "google/gemini-3-flash-preview"],
106
106
  balanced: ["openai/gpt-5.4", "anthropic/claude-sonnet-4.6", "google/gemini-2.5-pro", "openai/gpt-5.3", "google/gemini-3.1-pro"],
107
107
  powerful: ["openai/gpt-5.4-pro", "anthropic/claude-opus-4.6", "anthropic/claude-opus-4.5", "openai/o3", "openai/gpt-5.4"],
108
- cheap: ["nvidia/gpt-oss-120b", "nvidia/deepseek-v3.2", "google/gemini-2.5-flash", "deepseek/deepseek-chat", "openai/gpt-5.4-nano"],
108
+ cheap: ["zai/glm-5", "zai/glm-5-turbo", "nvidia/gpt-oss-120b", "nvidia/deepseek-v3.2", "google/gemini-2.5-flash", "deepseek/deepseek-chat", "openai/gpt-5.4-nano"],
109
109
  reasoning: ["openai/o3", "openai/o1", "openai/o3-mini", "deepseek/deepseek-reasoner", "openai/gpt-5.3-codex"],
110
- free: ["nvidia/gpt-oss-120b", "nvidia/deepseek-v3.2", "nvidia/nemotron-ultra-253b", "nvidia/nemotron-super-49b", "nvidia/qwen3-coder-480b", "nvidia/llama-4-maverick", "nvidia/gpt-oss-20b"],
111
- coding: ["openai/gpt-5.3-codex", "nvidia/qwen3-coder-480b", "nvidia/devstral-2-123b", "anthropic/claude-sonnet-4.6", "openai/gpt-5.4"]
110
+ free: ["nvidia/gpt-oss-120b", "nvidia/deepseek-v3.2", "nvidia/nemotron-ultra-253b", "nvidia/nemotron-super-49b", "nvidia/qwen3-coder-480b", "nvidia/llama-4-maverick", "nvidia/gpt-oss-20b", "nvidia/glm-4.7"],
111
+ coding: ["zai/glm-5", "openai/gpt-5.3-codex", "nvidia/qwen3-coder-480b", "nvidia/devstral-2-123b", "anthropic/claude-sonnet-4.6", "openai/gpt-5.4"],
112
+ glm: ["zai/glm-5", "zai/glm-5-turbo", "nvidia/glm-4.7"]
112
113
  };
113
114
 
114
115
  // src/utils/qr.ts
@@ -398,17 +399,23 @@ function registerChatTool(server, budget) {
398
399
  server.registerTool(
399
400
  "blockrun_chat",
400
401
  {
401
- description: `Get a second opinion from another AI model, or use a specialized model for a specific task. Useful when you want to cross-check analysis, use a reasoning model (o3, DeepSeek Reasoner) for hard problems, or use a free NVIDIA model for bulk tasks.
402
+ description: `Get a second opinion from another AI model, or use a specialized model for a specific task.
402
403
 
403
- Use routing:"smart" to auto-select the best model, or pick directly: model:"openai/o3", model:"deepseek/deepseek-reasoner", model:"nvidia/deepseek-v3.2" (free).
404
+ Notable modes:
405
+ - mode:"glm" \u2192 Zhipu GLM-5 / GLM-5-Turbo ($0.001/call, excellent for coding tasks, pays via USDC on BlockRun)
406
+ - mode:"coding" \u2192 GLM-5 first, then code-specialized models
407
+ - mode:"cheap" \u2192 GLM-5, NVIDIA free, DeepSeek
408
+ - mode:"reasoning" \u2192 o3, o1, DeepSeek-R1
409
+ - mode:"free" \u2192 NVIDIA models (no cost)
410
+ - routing:"smart" \u2192 auto-select via ClawRouter
404
411
 
405
- Prefer blockrun_search or blockrun_exa for research \u2014 they're purpose-built for that.
412
+ Pick directly: model:"zai/glm-5", model:"openai/o3", model:"nvidia/deepseek-v3.2" (free).
406
413
 
407
- Run blockrun_models to see all available models with pricing.`,
414
+ Run blockrun_models to see all 41+ models with pricing.`,
408
415
  inputSchema: {
409
416
  message: z2.string().describe("Your message to the AI"),
410
- model: z2.string().optional().describe("Specific model ID (e.g., 'openai/gpt-4o')"),
411
- mode: z2.enum(["fast", "balanced", "powerful", "cheap", "reasoning", "free", "coding"]).optional().describe("Smart routing mode (ignored if model specified)"),
417
+ model: z2.string().optional().describe("Specific model ID (e.g., 'zai/glm-5', 'openai/o3')"),
418
+ mode: z2.enum(["fast", "balanced", "powerful", "cheap", "reasoning", "free", "coding", "glm"]).optional().describe("Routing mode: glm = Zhipu GLM-5/GLM-5-Turbo ($0.001/call, great for coding), coding = GLM-5 + code models, cheap = GLM-5 + budget, free = NVIDIA only (ignored if model specified)"),
412
419
  routing: z2.enum(["smart"]).optional().describe('Set to "smart" to auto-select the optimal model via ClawRouter (14-dimension AI routing)'),
413
420
  routing_profile: z2.enum(["free", "eco", "auto", "premium"]).optional().default("auto").describe('Cost/quality profile for ClawRouter: "free" (zero cost NVIDIA), "eco" (budget), "auto" (balanced, default), "premium" (best quality) (only applies when routing: "smart")'),
414
421
  system: z2.string().optional().describe("Optional system prompt"),
@@ -1031,6 +1038,175 @@ ${lines.join("\n\n")}` }],
1031
1038
  );
1032
1039
  }
1033
1040
 
1041
+ // src/tools/glm-vision.ts
1042
+ import { z as z10 } from "zod";
1043
+ var ZHIPU_BASE_URL = "https://open.bigmodel.cn/api/paas/v4";
1044
+ async function callGLMVision(model, prompt, imageUrl, thinking = false) {
1045
+ const apiKey = process.env.ZHIPU_API_KEY;
1046
+ if (!apiKey) throw new Error("ZHIPU_API_KEY environment variable is required for GLM Vision");
1047
+ const payload = {
1048
+ model,
1049
+ messages: [
1050
+ {
1051
+ role: "user",
1052
+ content: [
1053
+ { type: "image_url", image_url: { url: imageUrl } },
1054
+ { type: "text", text: prompt }
1055
+ ]
1056
+ }
1057
+ ],
1058
+ temperature: 0.8,
1059
+ top_p: 0.6,
1060
+ max_tokens: 16384,
1061
+ stream: false
1062
+ };
1063
+ if (thinking || model.includes("thinking")) {
1064
+ payload["thinking"] = { type: "enabled" };
1065
+ }
1066
+ const res = await fetch(`${ZHIPU_BASE_URL}/chat/completions`, {
1067
+ method: "POST",
1068
+ headers: {
1069
+ "Content-Type": "application/json",
1070
+ Authorization: `Bearer ${apiKey}`
1071
+ },
1072
+ body: JSON.stringify(payload)
1073
+ });
1074
+ if (!res.ok) {
1075
+ const err = await res.text().catch(() => res.statusText);
1076
+ throw new Error(`GLM Vision API error ${res.status}: ${err}`);
1077
+ }
1078
+ const data = await res.json();
1079
+ const choice = data.choices?.[0];
1080
+ if (!choice) throw new Error("No response from GLM Vision");
1081
+ if (choice.finish_reason === "sensitive") throw new Error("Content blocked by safety filter");
1082
+ return choice.message.content;
1083
+ }
1084
+ async function callGLMOCR(fileUrl, startPage = 1, endPage) {
1085
+ const apiKey = process.env.ZHIPU_API_KEY;
1086
+ if (!apiKey) throw new Error("ZHIPU_API_KEY environment variable is required for GLM OCR");
1087
+ const payload = {
1088
+ model: "glm-ocr",
1089
+ file: fileUrl,
1090
+ return_crop_images: false,
1091
+ need_layout_visualization: false,
1092
+ start_page_id: startPage
1093
+ };
1094
+ if (endPage) payload["end_page_id"] = endPage;
1095
+ const res = await fetch(`${ZHIPU_BASE_URL}/layout_parsing`, {
1096
+ method: "POST",
1097
+ headers: {
1098
+ "Content-Type": "application/json",
1099
+ Authorization: `Bearer ${apiKey}`
1100
+ },
1101
+ body: JSON.stringify(payload)
1102
+ });
1103
+ if (!res.ok) {
1104
+ const err = await res.text().catch(() => res.statusText);
1105
+ throw new Error(`GLM OCR API error ${res.status}: ${err}`);
1106
+ }
1107
+ const data = await res.json();
1108
+ return data.markdown_result || data.choices?.[0]?.message?.content || JSON.stringify(data);
1109
+ }
1110
+ async function callGLMImageGen(prompt, size, quality) {
1111
+ const apiKey = process.env.ZHIPU_API_KEY;
1112
+ if (!apiKey) throw new Error("ZHIPU_API_KEY environment variable is required for GLM Image Gen");
1113
+ const res = await fetch(`${ZHIPU_BASE_URL}/images/generations`, {
1114
+ method: "POST",
1115
+ headers: {
1116
+ "Content-Type": "application/json",
1117
+ Authorization: `Bearer ${apiKey}`
1118
+ },
1119
+ body: JSON.stringify({
1120
+ model: "cogview-4-250304",
1121
+ prompt,
1122
+ size,
1123
+ quality,
1124
+ watermark_enabled: false
1125
+ })
1126
+ });
1127
+ if (!res.ok) {
1128
+ const err = await res.text().catch(() => res.statusText);
1129
+ throw new Error(`GLM Image API error ${res.status}: ${err}`);
1130
+ }
1131
+ const data = await res.json();
1132
+ const url = data.data?.[0]?.url;
1133
+ if (!url) throw new Error("No image URL in GLM response");
1134
+ return url;
1135
+ }
1136
+ function registerGLMVisionTool(server) {
1137
+ server.registerTool(
1138
+ "blockrun_glm_vision",
1139
+ {
1140
+ description: `Analyze images and documents using Zhipu AI's GLM vision models.
1141
+
1142
+ Requires ZHIPU_API_KEY environment variable.
1143
+
1144
+ Actions:
1145
+ - caption: Describe what's in an image
1146
+ - analyze: Deep analysis of an image (objects, layout, text, colors)
1147
+ - grounding: Locate specific elements in an image (returns bounding boxes)
1148
+ - code: Generate code from a UI screenshot or mockup
1149
+ - ocr: Extract text from a document/PDF (use file URL)
1150
+ - imagegen: Generate an image using CogView-4
1151
+
1152
+ Models:
1153
+ - glm-4.6v (default): Best quality vision model
1154
+ - glm-4.6v-flash: Faster, cheaper
1155
+ - glm-4.1v-thinking-flash: With reasoning/thinking
1156
+
1157
+ Cost: Zhipu AI pricing (separate from BlockRun x402 \u2014 uses ZHIPU_API_KEY)`,
1158
+ inputSchema: {
1159
+ action: z10.enum(["caption", "analyze", "grounding", "code", "ocr", "imagegen"]).describe("Task to perform"),
1160
+ image: z10.string().optional().describe("Image URL or base64 data URI (for vision actions)"),
1161
+ prompt: z10.string().optional().describe("Custom prompt or question about the image. For imagegen: the image description"),
1162
+ model: z10.enum(["glm-4.6v", "glm-4.6v-flash", "glm-4.1v-thinking-flash"]).optional().default("glm-4.6v").describe("Vision model to use"),
1163
+ size: z10.enum(["1280x1280", "1280x720", "720x1280", "1024x1024"]).optional().default("1280x1280").describe("Image size (for imagegen)"),
1164
+ quality: z10.enum(["hd", "standard"]).optional().default("hd").describe("Image quality (for imagegen)"),
1165
+ start_page: z10.number().optional().default(1).describe("Start page for OCR (PDF)"),
1166
+ end_page: z10.number().optional().describe("End page for OCR (PDF)")
1167
+ }
1168
+ },
1169
+ async ({ action, image, prompt, model, size, quality, start_page, end_page }) => {
1170
+ try {
1171
+ if (action === "imagegen") {
1172
+ const imagePrompt = prompt || image || "";
1173
+ if (!imagePrompt) {
1174
+ return { content: [{ type: "text", text: formatError("prompt is required for imagegen action") }], isError: true };
1175
+ }
1176
+ const url = await callGLMImageGen(imagePrompt, size ?? "1280x1280", quality ?? "hd");
1177
+ return {
1178
+ content: [{ type: "text", text: `Generated image: ${url}` }],
1179
+ structuredContent: { url }
1180
+ };
1181
+ }
1182
+ if (action === "ocr") {
1183
+ const fileUrl = image || prompt;
1184
+ if (!fileUrl) {
1185
+ return { content: [{ type: "text", text: formatError("image (PDF URL) is required for OCR") }], isError: true };
1186
+ }
1187
+ const result2 = await callGLMOCR(fileUrl, start_page ?? 1, end_page);
1188
+ return { content: [{ type: "text", text: result2 }] };
1189
+ }
1190
+ if (!image) {
1191
+ return { content: [{ type: "text", text: formatError("image is required for vision actions") }], isError: true };
1192
+ }
1193
+ const actionPrompts = {
1194
+ caption: "Describe this image concisely and accurately.",
1195
+ analyze: "Analyze this image in detail: describe all visible objects, layout, colors, text, and any notable features.",
1196
+ grounding: `Locate the following elements in the image and return their bounding boxes in [x1,y1,x2,y2] format (0-1000 normalized): ${prompt || "all interactive UI elements"}`,
1197
+ code: "Generate complete, working code to replicate this UI. Use React + TypeScript + Tailwind CSS. Include all components, styling, and mock data visible in the screenshot."
1198
+ };
1199
+ const visionPrompt = actionPrompts[action] || prompt || actionPrompts.caption;
1200
+ const result = await callGLMVision(model ?? "glm-4.6v", visionPrompt, image);
1201
+ return { content: [{ type: "text", text: result }] };
1202
+ } catch (err) {
1203
+ const errMsg = err instanceof Error ? err.message : String(err);
1204
+ return { content: [{ type: "text", text: formatError(errMsg) }], isError: true };
1205
+ }
1206
+ }
1207
+ );
1208
+ }
1209
+
1034
1210
  // src/mcp-handler.ts
1035
1211
  function initializeMcpServer(server) {
1036
1212
  const budget = { limit: null, spent: 0, calls: 0, agents: /* @__PURE__ */ new Map() };
@@ -1044,6 +1220,9 @@ function initializeMcpServer(server) {
1044
1220
  registerExaTool(server);
1045
1221
  registerMarketsTool(server);
1046
1222
  registerDexTool(server);
1223
+ if (process.env.ZHIPU_API_KEY) {
1224
+ registerGLMVisionTool(server);
1225
+ }
1047
1226
  server.registerResource(
1048
1227
  "wallet",
1049
1228
  "blockrun://wallet",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/mcp",
3
- "version": "0.6.9",
3
+ "version": "0.7.0",
4
4
  "mcpName": "io.github.BlockRunAI/blockrun-mcp",
5
5
  "description": "BlockRun MCP Server - Give your AI agent web search, deep research, prediction markets, crypto data, X/Twitter intelligence. Paid via x402 micropayments.",
6
6
  "type": "module",