mirror of
https://github.com/hanzoai/mcp.git
synced 2026-10-29 02:55:49 +00:00
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Successful in 2m14s
Hanzo CI/CD / test-amd64 (push) Successful in 6m17s
Hanzo CI/CD / cicd (push) Successful in 4m15s
CI/CD / cicd (push) Successful in 10m38s
The release lane built Linux alone, so hanzo.sh offered macOS and Windows a server nobody had built, and `hanzo dev` there fell back to nothing. It now cross-builds linux, windows and darwin for both architectures from the one Linux pool with Zig and a pinned macOS SDK, the way the CLI's release does, one target at a time. Zig comes from its own checksummed tarball, not pip. `hanzo dev` hands its server `--project-dir`, the native spelling. The npm build read it as stray arguments and exited, so a machine whose PATH found the npm `hanzo-mcp` first ran every session without the toolset. It now takes the flag as an allowed root. Claude-Session: https://claude.ai/code/session_01M8RoubcPN71KgJuZ8LdBUL
65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
/**
|
|
* Shared helper utilities for Hanzo Kai MCP Cookbook recipes.
|
|
*/
|
|
|
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
import { createMCPServer } from "../dist/index.js";
|
|
|
|
export interface RecipeResult {
|
|
recipe: string;
|
|
tool: string;
|
|
success: boolean;
|
|
latency_ms?: number;
|
|
output: any;
|
|
explanation: string;
|
|
}
|
|
|
|
/**
|
|
* Creates an in-process MCP client connected directly to the Hanzo MCP server.
|
|
* Enables zero-overhead execution for recipes and automated test suites.
|
|
*/
|
|
export async function createRecipeClient() {
|
|
// Kai is reached as every client reaches it: api.hanzo.ai with HANZO_API_KEY, or LOCAL_KAI_URL for a local `kai serve`.
|
|
const server = await createMCPServer({ name: "kai-cookbook-server", version: "2.4.20" });
|
|
// Call tools directly via server handlers or in-memory transport
|
|
return {
|
|
server,
|
|
async callTool(name: string, args: Record<string, any>) {
|
|
const tool = server.tools.find((t: any) => t.name === name);
|
|
if (!tool) throw new Error(`Tool '${name}' not found on server`);
|
|
const start = performance.now();
|
|
const res = await tool.handler(args);
|
|
const elapsed = performance.now() - start;
|
|
if (res.isError) {
|
|
return {
|
|
isError: true,
|
|
error: res.content?.[0]?.text || "Unknown error",
|
|
latency_ms: elapsed
|
|
};
|
|
}
|
|
let parsed = {};
|
|
try {
|
|
parsed = JSON.parse(res.content?.[0]?.text || "{}");
|
|
} catch {
|
|
parsed = { raw: res.content?.[0]?.text };
|
|
}
|
|
return {
|
|
isError: false,
|
|
data: parsed,
|
|
latency_ms: elapsed
|
|
};
|
|
}
|
|
};
|
|
}
|
|
|
|
export function logRecipe(result: RecipeResult) {
|
|
console.log(`\n======================================================`);
|
|
console.log(`📖 Recipe: ${result.recipe}`);
|
|
console.log(`🛠️ Tool: ${result.tool}`);
|
|
console.log(`⚡ Latency: ${result.latency_ms?.toFixed(2)} ms`);
|
|
console.log(`📝 Output:\n${JSON.stringify(result.output, null, 2)}`);
|
|
console.log(`💡 ${result.explanation}`);
|
|
console.log(`======================================================\n`);
|
|
}
|