Skip to main content
Glama
README.md
# agents-mcp-server

[![CI](https://github.com/agentsmcp/agents-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/agentsmcp/agents-mcp-server/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Node](https://img.shields.io/badge/node-%E2%89%A522-brightgreen.svg)](.nvmrc)

A monorepo of focused **MCP (Model Context Protocol) servers** that give an AI
agent safe, composable access to web3 market data and trading — split by concern
so that *reading* the chain and *acting* on it are never the same surface.

- **Read-only intelligence & data** servers expose on-chain analytics and market
  data. They never sign or send anything.
- **Execution** servers place trades and swaps, and gate every action behind an
  explicit `SIM | PAPER | LIVE` mode so an agent can never accidentally move funds.
- A tiny shared framework (`@agentsmcp/mcp-core`) makes every server a flat
  **registry of tool modules** — adding a tool is one file, not a new `switch` arm.

> Built with TypeScript (strict, ESM, Node ≥22), the MCP SDK, Zod, and Vitest;
> formatted/linted with Biome; secrets encrypted at rest with dotenvx.

---

## Architecture

```mermaid
flowchart TB
  agent["AI agent / MCP client"]

  subgraph readonly["Read-only servers (no signing)"]
    intel["web3-intel<br/>9 tools · wallet & token intelligence"]
    market["web3-market-data<br/>15 tools · multi-venue market data"]
  end

  subgraph exec["Execution servers (SIM · PAPER · LIVE)"]
    hl["web3-hyperliquid-trading<br/>4 tools · perps"]
    onchain["web3-onchain-trading<br/>6 tools · 0x + Jupiter swaps"]
  end

  subgraph core["Shared packages"]
    mcpcore["@agentsmcp/mcp-core<br/>tool registry · stdio runtime · CLI"]
    providers["web3-core-onchain<br/>Alchemy · Helius · 0x · Jupiter · Codex"]
    wallets["web3-core-wallets<br/>encrypted wallet resolution"]
    norm["web3-core-hyperliquid<br/>position/account normalization"]
  end

  ext["External APIs<br/>Alchemy · Helius · Codex · Hyperliquid · 0x · Jupiter"]

  agent -- stdio/JSON-RPC --> intel & market & hl & onchain
  intel & market & hl & onchain --> mcpcore
  intel & market & onchain --> providers
  hl & onchain --> wallets
  market --> norm
  providers --> ext
  hl --> ext
```

| Server | Kind | Tools | Talks to |
| --- | --- | --- | --- |
| [`web3-intel`](web3-intel) | read-only | 9 | Alchemy, Helius, Codex |
| [`web3-market-data`](web3-market-data) | read-only | 15 | Hyperliquid, Alchemy, Helius |
| [`web3-hyperliquid-trading`](web3-hyperliquid-trading) | execution | 4 | Hyperliquid |
| [`web3-onchain-trading`](web3-onchain-trading) | execution | 6 | 0x (EVM), Jupiter (Solana) |

Shared packages: [`@agentsmcp/mcp-core`](packages/mcp-core) ·
[`web3-core-onchain`](packages/web3-core-onchain) ·
[`web3-core-wallets`](packages/web3-core-wallets) ·
[`web3-core-hyperliquid`](packages/web3-core-hyperliquid) ·
[`mcp-test-harness`](packages/mcp-test-harness).

## The tool-registry pattern

Every server is just a list of `ToolDefinition`s wired through `mcp-core`. There
is no per-server `switch`, no repeated server bootstrap, and no duplicated CLI.

```ts
// web3-onchain-trading/src/tools/zerox.ts
import { type ToolDefinition, jsonText } from '@agentsmcp/mcp-core';

export const getQuote0x: ToolDefinition = {
  name: 'get_quote_0x',
  description: 'Get a 0x swap quote for an EVM trade…',
  inputSchema: zeroXQuoteInputJsonSchema,
  annotations: { readOnlyHint: true },
  async handler(rawArgs, deps) {
    const { args, quote, fee } = await fetch0xQuote(rawArgs, deps); // deps.fetch is injectable
    return jsonText({ provider: '0x', ...args, fee, quote });
  },
};
```

```ts
// web3-onchain-trading/src/index.ts — the whole server
import { createToolRouter } from '@agentsmcp/mcp-core';
import { tools } from './tools/index.js';

export function createOnchainTradingRouter(deps?) {
  return createToolRouter(tools, { serverName: 'web3-onchain-trading', deps });
}
```

`createToolRouter` dispatches by name via a `Map` and wraps every failure as
`"<server> <tool> failed: …"`. `runStdioServer` and `runCli` (in `cli.ts`)
provide the SDK server and the dotenvx bootstrap. **Adding a tool** = write one
`tools/*.ts` module and add it to the `tools` array.

The injectable `deps.fetch` is the testing seam: handlers are unit-tested by
passing a mock `fetch`, with no network and no live keys (see any `*.mock.test.ts`).

## Execution safety: SIM · PAPER · LIVE

Every execution tool requires a `mode`:

- **SIM / PAPER** — never touch the network and never resolve wallet secrets;
  they return exactly what *would* be sent. Safe for an agent to call freely.
- **LIVE** — the only mode that signs and broadcasts. It resolves the selected
  wallet on demand and (for Hyperliquid) verifies the account matches the wallet.

Wallet **private keys are never stored in code or JSON**. A wallet file holds
metadata plus pointers to env vars; the actual secrets live in an
[dotenvx](https://dotenvx.com)-encrypted `~/.agentsmcp/.env`.

## Quickstart

```bash
pnpm install
pnpm build                 # build all packages
pnpm test                  # unit + mock + contract tests (e2e auto-skip)
pnpm check                 # Biome + MCP registry validation

# configure secrets / wallet (see .env.example for every variable)
pnpm wallet add main       # create an encrypted wallet
pnpm env:set ALCHEMY_API_KEY <key>
```

Run a server over stdio (e.g. with the MCP Inspector):

```bash
pnpm --filter @agentsmcp/web3-intel inspect
```

Point an MCP client at the server's `dist/cli.js` (each package ships a `bin`).

## Testing

```bash
pnpm test                  # all workspaces, sequential + visible output
pnpm test:coverage         # with V8 coverage report
RUN_E2E=1 pnpm test        # also run live-API e2e tests (needs real keys)
```

Tests are layered: **contract** tests spawn the built server over stdio and
assert its tool list; **mock** tests exercise handlers with an injected `fetch`;
**e2e** tests hit real APIs and are gated behind `RUN_E2E=1` so a normal run is
fast and offline.

## Repository layout

```
packages/
  mcp-core/             # tool registry + stdio runtime + CLI bootstrap (the framework)
  web3-core-onchain/    # Alchemy/Helius/0x/Jupiter/Codex providers + request builders
  web3-core-wallets/    # wallet metadata + encrypted secret resolution
  web3-core-hyperliquid/# Hyperliquid position/account normalization
  mcp-test-harness/     # McpStdioClient used by contract/e2e tests
web3-intel/             # read-only intelligence server
web3-market-data/       # read-only market-data server
web3-hyperliquid-trading/  # perps execution server
web3-onchain-trading/   # spot-swap execution server
web/docs/               # Astro/Starlight documentation site
scripts/                # wallet CLI, registry validation, publish
```

See [ARCHITECTURE.md](ARCHITECTURE.md) for a deeper tour, and
[.env.example](.env.example) for every environment variable.

## License

[MIT](LICENSE)