elytra_scan
Scan code snippets for security vulnerabilities across 11 languages and IaC. Obtain severity ratings, fix suggestions, and a security score.
Instructions
Scan a code snippet for security vulnerabilities. Supports Solidity, Vyper, JS/TS, Python, Go, Rust, Java, Ruby, PHP, plus IaC (Terraform, Kubernetes, Dockerfile, GitHub Actions). Returns findings with severity, fix suggestions, and a 0-100 score. Use this for security-focused code review.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | The source code to scan | |
| language | No | Language hint: javascript | typescript | python | go | java | ruby | php | solidity | rust | javascript |
Implementation Reference
- src/index.ts:202-210 (handler)Tool handler: Sends code to the Elytra API /api/playground endpoint and formats the scan result.
async function runScan(args: { code?: string; language?: string }): Promise<ToolResponse> { if (!args.code) return errOut("Missing required field: code"); const r = await postJSON<ScanResult>("/api/playground", { code: args.code, language: args.language ?? "javascript", }); if (!("ok" in r)) return errOut(r.error); return { content: [{ type: "text", text: formatScan(r.data, "Scan result") }] }; } - src/index.ts:144-155 (schema)Input schema definition for elytra_scan: requires 'code' (string), optional 'language' (string, default 'javascript').
{ name: "elytra_scan", description: "Scan a code snippet for security vulnerabilities. Supports Solidity, Vyper, JS/TS, Python, Go, Rust, Java, Ruby, PHP, plus IaC (Terraform, Kubernetes, Dockerfile, GitHub Actions). Returns findings with severity, fix suggestions, and a 0-100 score. Use this for security-focused code review.", inputSchema: { type: "object", properties: { code: { type: "string", description: "The source code to scan" }, language: { type: "string", description: "Language hint: javascript | typescript | python | go | java | ruby | php | solidity | rust", default: "javascript" }, }, required: ["code"], }, - src/index.ts:291-304 (registration)Registration of all tools in the MCP CallToolRequestSchema handler. elytra_scan is dispatched to runScan.
server.setRequestHandler(CallToolRequestSchema, async (req) => { const { name, arguments: args = {} } = req.params; try { switch (name) { case "elytra_scan": return await runScan(args as { code?: string; language?: string }); case "elytra_scan_address": return await runScanAddress(args as { address?: string; chain?: string }); case "elytra_replay_hacks": return await runReplayHacks(args as { code?: string; language?: string }); case "elytra_agent_identity": return await runAgentIdentity(); default: return errOut(`Unknown tool: ${name}`); } } catch (e) { return errOut(e instanceof Error ? e.message : "Internal MCP server error"); } }); - src/index.ts:143-189 (registration)Tool registration array exposed via ListToolsRequestSchema, containing the elytra_scan definition.
const TOOLS = [ { name: "elytra_scan", description: "Scan a code snippet for security vulnerabilities. Supports Solidity, Vyper, JS/TS, Python, Go, Rust, Java, Ruby, PHP, plus IaC (Terraform, Kubernetes, Dockerfile, GitHub Actions). Returns findings with severity, fix suggestions, and a 0-100 score. Use this for security-focused code review.", inputSchema: { type: "object", properties: { code: { type: "string", description: "The source code to scan" }, language: { type: "string", description: "Language hint: javascript | typescript | python | go | java | ruby | php | solidity | rust", default: "javascript" }, }, required: ["code"], }, }, { name: "elytra_scan_address", description: "Scan a DEPLOYED smart contract by its onchain address. Elytra fetches the verified source from the block explorer (Etherscan / Basescan / etc.) and scans every source file. Use this when the user gives you a 0x... address and asks about its security.", inputSchema: { type: "object", properties: { address: { type: "string", description: "Contract address (0x... 40 hex chars)" }, chain: { type: "string", description: "ethereum | base | arbitrum | optimism | polygon", default: "ethereum" }, }, required: ["address"], }, }, { name: "elytra_replay_hacks", description: "Run the 12 famous-exploit pattern detectors against submitted source code. Encodes patterns from $3.04B in losses: Bybit ($1.46B), Ronin ($625M), Wormhole ($325M), Euler ($197M), Nomad ($190M), Beanstalk ($182M), Cream ($130M), Multichain ($126M), Mango ($114M), Curve ($73M), Radiant ($53M), zkSync ($5M). Returns only matches against these specific historic attack vectors. Use this when you want to check 'have I made any of the famous mistakes?'", inputSchema: { type: "object", properties: { code: { type: "string", description: "The source code to test against hack-replay patterns" }, language: { type: "string", description: "Language hint", default: "solidity" }, }, required: ["code"], }, }, { name: "elytra_agent_identity", description: "Return Elytra's onchain agent identity card — ERC-8004 registry data, capabilities, pricing on Base and Solana, attestation count, and discovery endpoints. Use this when the user wants to verify or learn about the Elytra agent itself, integrate it programmatically, or compare it to other agents.", inputSchema: { type: "object", properties: {} }, }, ]; - src/index.ts:36-55 (helper)Helper: Generic HTTP POST function used by runScan to call the Elytra API.
async function postJSON<T>(path: string, body: unknown, opts: { auth?: boolean } = {}): Promise<RestResult<T>> { const headers: Record<string, string> = { "Content-Type": "application/json" }; if (opts.auth && API_KEY) headers.Authorization = `Bearer ${API_KEY}`; let res: Response; try { res = await fetch(`${BASE_URL}${path}`, { method: "POST", headers, body: JSON.stringify(body) }); } catch (e) { return { error: `Network error reaching Elytra: ${e instanceof Error ? e.message : "unknown"}`, status: 0 }; } let data: unknown; try { data = await res.json(); } catch { data = null; } if (!res.ok) { const errMsg = (data as { error?: string })?.error ?? `HTTP ${res.status}`; return { error: errMsg, status: res.status }; } return { ok: true, data: data as T }; }