Skip to main content
Glama
index.ts4.59 kB
#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { MinaGraphQLClient ,BlockStatusFilter } from "./graphql-client.js"; import { z } from "zod"; import yargs from "yargs"; import { hideBin } from "yargs/helpers"; const ConfigSchema = z.object({ name: z.string().default("mcp-graphql"), endpoint: z.string().url().default("http://archive-node-api.gcp.o1test.net/"), }); type Config = z.infer<typeof ConfigSchema>; function parseArgs(): Config { const argv = yargs(hideBin(process.argv)) .option("name", { type: "string", description: "Name of the MCP server", default: "mcp-mina-archive-node", }) .option("endpoint", { type: "string", description: "Archive Node API endpoint", default: "http://archive-node-api.gcp.o1test.net/", }) .help() .parseSync(); try { return ConfigSchema.parse({ name: argv.name, endpoint: argv.endpoint, }); } catch (error) { if (error instanceof z.ZodError) { console.error("Invalid config:"); console.error( error.errors .map((e) => ` ${e.path.join(".")}: ${e.message}`) .join("\n"), ); } else { console.error("Error parsing arguments:", error); } process.exit(1); } } const config = parseArgs(); const minaClient = new MinaGraphQLClient(config.endpoint); const server = new McpServer({ name: "mina-archive-node", version: "1.0.0", description: "MCP Server for Mina Archive Node API" }); server.tool( "query-actions", "Query actions from the Mina blockchain with optional filters", { address: z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{55,60}$/, 'Invalid Ethereum address format'), tokenId: z.string().optional().describe("Token ID to filter transactions"), status: z.enum(Object.values(BlockStatusFilter) as [BlockStatusFilter, ...BlockStatusFilter[]]).optional().describe("Transaction status to filter"), to: z.number().optional().describe("Block height to filter transactions"), from: z.number().optional().describe("Block height to filter transactions"), fromActionState: z.string().optional().describe("Action state to filter transactions"), endActionState: z.string().optional().describe("Action state to filter transactions"), }, async ({ address, tokenId, status, to, from, fromActionState, endActionState }) => { try { const result = await minaClient.queryActions({address, tokenId, status, to, from, fromActionState, endActionState}); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error) { throw new Error(`Failed to query actions: ${error}`); } } ); server.tool( "query-events", "Query events from the Mina blockchain with optional filters", { address: z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{55,60}$/, 'Invalid Ethereum address format'), tokenId: z.string().optional().describe("Token ID to filter transactions"), status: z.enum(Object.values(BlockStatusFilter) as [BlockStatusFilter, ...BlockStatusFilter[]]).optional().describe("Transaction status to filter"), to: z.number().optional().describe("Block height to filter transactions"), from: z.number().optional().describe("Block height to filter transactions"), }, async ({ address, tokenId, status, to, from }) => { try { const result = await minaClient.queryEvents({address, tokenId, status, to, from}); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error) { throw new Error(`Failed to query events: ${error}`); } } ); server.tool( "get-network-state", "Get the current state of the Mina network", {}, async () => { try { const result = await minaClient.queryNetworkState(); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error) { throw new Error(`Failed to get network state: ${error}`); } } ); // Start the server async function main() { try { // Use stdio transport for communication const transport = new StdioServerTransport(); await server.connect(transport); console.error(`Started Mina MCP server for archive node API for endpoint: ${config.endpoint}`,); } catch (error) { console.error(`Fatal error in main(): ${error}`); process.exit(1); } } main();

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/boray/mcp-mina-archive-node'

If you have feedback or need assistance with the MCP directory API, please join our Discord server