uniswap-tx-builder

Yummybait-fin/uniswap-tx-builder-mcp
0 starsApache-2.0Community

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

A keyless MCP server that builds unsigned Uniswap v3 liquidity-position transactions and optionally simulates them via eth_call; it never holds keys or signs.

README.md

uniswap-tx-builder-mcp

A keyless MCP server that builds unsigned Uniswap v3 liquidity-position transactions and optionally simulates them via eth_call. It never holds keys and never signs — you take the returned calldata and sign + broadcast it with your own wallet (viem, a CDP wallet MCP, any signer).

Because it's keyless, the only limits that apply to a built tx are your wallet's — the server's threat surface is just "it returns calldata and reads public RPCs."

Tools

Every build tool returns tx = { to, data, value, chainId } (value is always "0") plus a human description. Addresses are 0x…40; positionId and amounts are decimal strings (they exceed JS safe integers).

| Tool | Purpose | |------|---------| | build_collect | Collect all uncollected fees from a position to recipient. | | build_close | Remove all liquidity + collect; burn: true also burns the empty NFT. Returns the read position. | | build_mint | Mint a new position (raw ticks + wei amounts). | | build_increase | Add liquidity to an existing position. | | plan_position | Read-only. Turn a human price range + human amounts into aligned ticks + wei amounts for build_mint. Reads token decimals over RPC. |

simulate runs an opt-in eth_call dry-run: on by default for collect/close, off for mint/increase (those need approvals + balances, so the dry-run usually reverts). A reverted simulation comes back as an error — don't sign a tx that failed to simulate. See the companion skill for the full argument reference and position lifecycle.

Install & run

npm install
npm run dev                 # stdio MCP from source via tsx
npm run build && npm start  # compile to dist/, then run the built server
npm test                    # vitest

Set MCP_HTTP_PORT to serve the streamable-HTTP transport instead of stdio (endpoint: http://<host>:<port>/mcp):

MCP_HTTP_PORT=8102 npm run dev

Docker — build locally, or pull a released image from GHCR:

docker build -t uniswap-tx-builder-mcp:local .                        # local build
docker pull ghcr.io/yummybait-fin/uniswap-tx-builder-mcp:latest       # released image

docker run -i --rm uniswap-tx-builder-mcp:local                       # stdio
docker run --rm -p 8102:8102 -e MCP_HTTP_PORT=8102 uniswap-tx-builder-mcp:local  # HTTP

Connect to an MCP client

Claude Code (stdio, from a local build):

npm run build
claude mcp add uniswap-tx-builder -- node /abs/path/to/uniswap-tx-builder-mcp/dist/mcp.js

Generic client config (Claude Desktop, etc.) — add to the client's mcpServers:

{
  "mcpServers": {
    "uniswap-tx-builder": {
      "command": "node",
      "args": ["/abs/path/to/uniswap-tx-builder-mcp/dist/mcp.js"],
      "env": { "RPC_ETH": "https://your-eth-rpc" }
    }
  }
}

For HTTP, run the server with MCP_HTTP_PORT and point the client at http://<host>:<port>/mcp.

Install the companion skill

skills/uniswap-tx-builder/ is a generic agent skill (no app- or wallet-specific knowledge) that teaches an agent how to drive these tools: the argument reference, simulate-first, the close→mint rebalance sequence, and the "your wallet signs" handoff. It pairs with the MCP — install both. Pick whichever install path suits you.

A. Claude Code plugin (/plugin) — the repo doubles as a plugin marketplace:

/plugin marketplace add Yummybait-fin/uniswap-tx-builder-mcp
/plugin install uniswap-tx-builder@yummybait

B. npx — copies the skill into a skills dir (no clone needed):

# personal (~/.claude/skills, every project)
npx -p github:Yummybait-fin/uniswap-tx-builder-mcp uniswap-tx-builder-skill

# or project-scoped (./.claude/skills, checked in with a repo)
npx -p github:Yummybait-fin/uniswap-tx-builder-mcp uniswap-tx-builder-skill --project

C. Manual copy — straight from a checkout:

cp -r skills/uniswap-tx-builder ~/.claude/skills/                       # personal
mkdir -p .claude/skills && cp -r skills/uniswap-tx-builder .claude/skills/  # project

The agent picks it up by its SKILL.md frontmatter — no restart needed for project skills.

Configuration

Per-chain RPCs default to public endpoints; override with env vars (see src/config.ts):

| Chain | ID | RPC env var | |-------|----|-------------| | Ethereum | 1 | RPC_ETH | | Optimism | 10 | RPC_OP | | Polygon | 137 | RPC_POLYGON | | Base | 8453 | RPC_BASE | | Arbitrum | 42161 | RPC_ARB |

Public RPCs are rate-limited and best-effort — set your own for anything beyond casual use.

Architecture

One code path, transport kept separate so it stays testable and ready for a future v4 tool set:

builder.ts     calldata encoding (viem) + position reads
ticks.ts       pure price ↔ tick math (no I/O)
operations.ts  build + optional eth_call simulate + response shaping
mcp.ts         the MCP transport (stdio / streamable HTTP)

CI / releases

GitHub Actions (.github/workflows/):

  • CI — typecheck + tests on every push to main and on PRs.
  • Release — pushing a v* tag re-runs the tests, bumps the version on main to match the tag

(package.json + .claude-plugin/plugin.json), then builds and publishes the Docker image to GHCR (ghcr.io/yummybait-fin/uniswap-tx-builder-mcp), tagged with the version (and latest). The bump lands on main after the tag, so the tagged commit keeps its old version.

package.json is the single source of version truth: the MCP server reads it at startup (so the version it reports always matches), and the release job keeps plugin.json in lockstep.

git tag v0.3.0 && git push origin v0.3.0   # cut a release

Scope

Uniswap v3 NonfungiblePositionManager on the chains above. Calling an unconfigured chain returns an "Unsupported chain" error. Roadmap: Uniswap v4 as a separate set of tools alongside these.

Related MCP servers

Browse all →