Skill: rbcp18/teller-borrow (version 0.2.2)

--- name: tellermcp-mcp description: Expose the Teller delta-neutral + lending Model Context Protocol server. Use this when you need to install, run, or update the Tellermcp MCP backend so agents can fetch opportunities, borrow terms, and on-chain tx builders for Teller. --- # Tellermcp MCP Skill ## Overview This skill bundles a ready-to-run MCP server (`scripts/tellermcp-server/`) that surfaces Teller delta-neutral arbitrage data, borrow pool discovery, loan terms, borrow transaction builders, and repayment helpers. Load this skill whenever you must: - Deploy or modify the Tellermcp MCP server - Re-run `npm install`, build, or tests for the server - Register Tellermcp with mcporter/OpenClaw so agents can hit the Teller APIs via MCP tools ## Quick Start 1. `cd scripts/tellermcp-server` 2. `npm install` 3. (Optional) Configure env vars: - `TELLER_API_BASE_URL` (defaults to `https://delta-neutral-api.teller.org`) - `TELLER_API_TIMEOUT_MS` (defaults to `15000` ms) 4. `npm run build` → TypeScript type-check. 5. `npm start` → launches `tellermcp` MCP server over stdio. ## Repo Layout (`scripts/tellermcp-server/`) - `package.json` / `package-lock.json` – Node 20+ project metadata - `tsconfig.json` – ES2022/ESNext build targets - `src/client.ts` – Typed Teller REST client (fetch wrapper + filters) - `src/types.ts` – TypeScript interfaces for all Teller responses - `src/index.ts` – MCP server wiring (McpServer + StdioServerTransport) registering tools: 1. `get-delta-neutral-opportunities` 2. `get-borrow-pools` 3. `get-borrow-terms` 4. `build-borrow-transactions` 5. `get-wallet-loans` 6. `build-repay-transactions` Each tool returns: short text summary + `structuredContent.payload` containing the raw JSON for downstream automation. ## Runbook ### Installing dependencies ```bash cd scripts/tellermcp-server npm install ``` The project intentionally omits `node_modules/` & `dist/`; `npm install` and `npm run build` regenerate them. ### Local testing - `npm run build` → TypeScript compile. - `npm start` → STDIO MCP server. Use `gh pr checks` or `npm test` (placeholder) if additional tests are added later. ### Registering with mcporter / OpenClaw Add an entry to your `mcporter` (or agent transport) config: ```jsonc { "name": "tellermcp", "command": "npm", "args": ["start"], "cwd": [REDACTED_SECRET] } ``` Once mcporter restarts, Codex agents can invoke the six Teller tools directly. ### Deploying updates 1. Edit TypeScript files inside `src/`. 2. `npm run build` locally. 3. Commit + push via GitHub skill (if syncing to `teller-protocol/teller-mcp`). 4. Restart the mcporter process pointing at this repo to pick up changes. ## References - [references/delta-neutral-api.md](references/delta-neutral-api.md) – condensed Teller API cheat sheet (endpoints, params, caching behavior). Load when you need exact REST contract details. ## Packaging This Skill When ready to ship a `.skill` bundle: ```bash python3 /usr/local/lib/node_modules/openclaw/skills/skill-creator/scripts/package_skill.py /data/workspace/skills/tellermcp-mcp ``` The packager validates SKILL.md + resources and emits `tellermcp-mcp.skill` (zip) for distribution.

path: references/delta-neutral-api.md
content: # Teller Delta-Neutral + Lending API Cheat Sheet

Source: https://registry.scalar.com/@teller/apis/delta-neutral/latest

## Base URLs
- Production: `https://delta-neutral-api.teller.org`
- Local dev: `http://localhost:3000`

## Endpoints

### 1. `GET /perps/delta-neutral`
- Returns best delta-neutral arbitrage opportunities by `(chainId, coin)`.
- Key fields: `borrowAprPct`, `fundingAprYearlyPct`, `netAprPct`, `principalAvailableUsd`, `allPlatforms[]`.
- Cached for ~2 minutes.
- Use to decide which pool + perp venue combination yields positive net APR (borrow cost vs. negative perp funding).

### 2. `GET /borrow/general`
- Lists every Teller borrow pool.
- Filters: `chainId`, `collateral_token_address`, `borrow_token_address`, `pool_address`, `ttl`.
- Response includes enrichment: collateral ratio, principal available, marketplace fees, payment cycle.
- Cached ~30 minutes.

### 3. `GET /borrow-terms`
- Calculates how much a given wallet can borrow from a specific pool/collateral pair.
- Required params: `wallet`, `chainId`, `collateralToken`, `poolAddress`.
- Output: `maxBorrowUsd`, `ltvPct`, `principalAvailableUsd`, collateral balances, rates.

### 4. `GET /borrow-tx`
- Builds the on-chain transaction list needed to borrow (token approval, forwarder approval, commitment accept).
- Required params: `walletAddress`, `collateralTokenAddress`, `chainId`, `poolAddress`, `collateralAmount`, `principalAmount`.
- Optional `loanDuration` (seconds).
- Use results directly as calldata for sequential submission.

### 5. `GET /loans/get-all`
- Pulls the borrower’s complete loan list from the Teller subgraph.
- Params: `walletAddress`, `chainId`.
- Includes status, principal, APR, schedule, collateral info.

### 6. `GET /loans/repay-tx`
- Generates approval + repay transactions for full or partial repayment.
- Params: `bidId`, `chainId`, `walletAddress`, optional `amount`.
- Response matches `borrow-tx` structure: `transactions[]`, `summary` (repayment amount, lending token, etc.).

### Helper Notes
- All addresses should be 0x-prefixed, checksummed/lowercase; API normalizes but best to send canonical form.
- Amount fields for tx builder endpoints expect base units (wei, smallest token unit). Format as decimal strings.
- Errors typically return `{ "ok": false, "error": "message" }` with HTTP 4xx/5xx codes.


path: scripts/tellermcp-server/README.md
content: # tellermcp

An MCP (Model Context Protocol) server that lets agents pull Teller delta-neutral opportunities, borrow pool data, loan terms, and the on-chain transactions needed to borrow or repay directly from Teller's public Delta-Neutral API.

## Features

- 🔍 **Delta-neutral scanner** – surfaces opportunities filtered by chain, asset, minimum net APR, and hard limits.
- 🏦 **Borrow pool discovery** – lists every active Teller lending pool with optional chain/token filters.
- 📐 **Per-wallet borrow terms** – computes LTV, available principal, and max borrowable USD for any wallet/pool pairing.
- 🧾 **Borrow transaction builder** – returns the full set of encoded transactions (approvals + borrow call) ready to submit on-chain.
- 📊 **Loan portfolio view** – fetches all Teller loans tied to a wallet + chain.
- 💸 **Repay helper** – builds repayment approvals + repay transactions for full or partial paydowns.

Each tool returns a short text summary plus structured JSON under `structuredContent.payload`, so consuming agents get machine-usable data without extra parsing.

## Project layout

```
agents/tellermcp/
├── README.md              # this file
├── package.json           # npm metadata + scripts
├── tsconfig.json          # TypeScript config
└── src/
    ├── index.ts           # MCP server wiring + tool registration
    ├── client.ts          # typed Teller API client
    └── types.ts           # response interfaces used by the client
```

## Requirements

- Node.js 20+ (Node 22.22.0 is available in this workspace)
- npm (ships with Node)
- Internet access to `https://delta-neutral-api.teller.org`

## Setup & usage

```bash
cd agents/tellermcp
npm install           # already run, but safe to repeat
npm run build         # optional: type-check
npm start             # launches the MCP server over stdio
```

`npm start` runs `tsx src/index.ts`, which starts an `McpServer` using `StdioServerTransport`. Point any MCP-compatible agent (e.g., mcporter/OpenClaw) at this command to expose the tools.

### Environment variables

| Variable | Default | Purpose |
| --- | --- | --- |
| `TELLER_API_BASE_URL` | `https://delta-neutral-api.teller.org` | Override for self-hosted instances or local mocks |
| `TELLER_API_TIMEOUT_MS` | `15000` | Per-request timeout for Teller API calls (ms) |

## Available tools

| Tool name | What it does | Key inputs |
| --- | --- | --- |
| `get-delta-neutral-opportunities` | Returns filtered delta-neutral arb opportunities. | `chainId`, `coin`, `limit`, `minNetAprPct` (all optional) |
| `get-borrow-pools` | Lists Teller borrow pools with optional filters. | `chainId`, `collateralTokenAddress`, `borrowTokenAddress`, `poolAddress`, `ttl` |
| `get-borrow-terms` | Computes borrow capacity for a wallet + pool. | `wallet`, `chainId`, `collateralToken`, `poolAddress` |
| `build-borrow-transactions` | Generates encoded transactions required to borrow. | `walletAddress`, `collateralTokenAddress`, `chainId`, `poolAddress`, `collateralAmount`, `principalAmount`, `loanDuration` |
| `get-wallet-loans` | Pulls all Teller loans for a wallet. | `walletAddress`, `chainId` |
| `build-repay-transactions` | Builds repayment approval + repay calls. | `bidId`, `chainId`, `walletAddress`, `amount` (optional for partial) |

Every address input is validated (checksummed or lowercase) before hitting the Teller API, and all numeric inputs are sanity-checked.

## Integrating with OpenClaw / mcporter

Add a transport entry that spawns this server via stdio, for example:

```jsonc
{
  "name": "tellermcp",
  "command": "npm",
  "args": ["start"],
  "cwd": "/data/workspace/agents/tellermcp"
}
```

Once registered, the `tellermcp` agent exposes the six tools above to any Codex/OpenClaw session.

## Next steps

- Wire authentication if Teller ships private endpoints.
- Cache hot endpoints (e.g., `/perps/delta-neutral`) if rate limits become tight.
- Extend with rollover tooling once the API exposes builder endpoints.


path: scripts/tellermcp-server/package-lock.json
content: {
  "name": "tellermcp",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "tellermcp",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "@modelcontextprotocol/sdk": "^1.26.0",
        "zod": "^4.3.6"
      },
      "devDependencies": {
        "@types/node": "^25.2.3",
        "tsx": "^4.21.0",
        "typescript": "^5.9.3"
      }
    },
    "node_modules/@esbuild/aix-ppc64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "ppc64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "aix"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/android-arm": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/android-arm64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/android-x64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "android"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/darwin-arm64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/darwin-x64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/freebsd-arm64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "freebsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/freebsd-x64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "freebsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-arm": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-arm64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-ia32": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "ia32"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-loong64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "loong64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-mips64el": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "mips64el"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-ppc64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "ppc64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-riscv64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "riscv64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-s390x": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "s390x"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/linux-x64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "linux"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/netbsd-arm64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "netbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/netbsd-x64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "netbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/openbsd-arm64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/openbsd-x64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openbsd"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/openharmony-arm64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "openharmony"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/sunos-x64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "sunos"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/win32-arm64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "arm64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/win32-ia32": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "ia32"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@esbuild/win32-x64": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "cpu": [
        "x64"
      ],
      "dev": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "win32"
      ],
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/@hono/node-server": {
      "version": "1.19.9",
      "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=18.14.1"
      },
      "peerDependencies": {
        "hono": "^4"
      }
    },
    "node_modules/@modelcontextprotocol/sdk": {
      "version": "1.26.0",
      "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@hono/node-server": "^1.19.9",
        "ajv": "^8.17.1",
        "ajv-formats": "^3.0.1",
        "content-type": "^1.0.5",
        "cors": "^2.8.5",
        "cross-spawn": "^7.0.5",
        "eventsource": "^3.0.2",
        "eventsource-parser": "^3.0.0",
        "express": "^5.2.1",
        "express-rate-limit": "^8.2.1",
        "hono": "^4.11.4",
        "jose": "^6.1.3",
        "json-schema-typed": "^8.0.2",
        "pkce-challenge": "^5.0.0",
        "raw-body": "^3.0.0",
        "zod": "^3.25 || ^4.0",
        "zod-to-json-schema": "^3.25.1"
      },
      "engines": {
        "node": ">=18"
      },
      "peerDependencies": {
        "@cfworker/json-schema": "^4.1.1",
        "zod": "^3.25 || ^4.0"
      },
      "peerDependenciesMeta": {
        "@cfworker/json-schema": {
          "optional": true
        },
        "zod": {
          "optional": false
        }
      }
    },
    "node_modules/@types/node": {
      "version": "25.2.3",
      "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "undici-types": "~7.16.0"
      }
    },
    "node_modules/accepts": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "mime-types": "^3.0.0",
        "negotiator": "^1.0.0"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/ajv": {
      "version": "8.18.0",
      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "fast-deep-equal": "^3.1.3",
        "fast-uri": "^3.0.1",
        "json-schema-traverse": "^1.0.0",
        "require-from-string": "^2.0.2"
      },
      "funding": {
        "type": "github",
        "url": "https://github.com/sponsors/epoberezkin"
      }
    },
    "node_modules/ajv-formats": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ajv": "^8.0.0"
      },
      "peerDependencies": {
        "ajv": "^8.0.0"
      },
      "peerDependenciesMeta": {
        "ajv": {
          "optional": true
        }
      }
    },
    "node_modules/body-parser": {
      "version": "2.2.2",
      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "bytes": "^3.1.2",
        "content-type": "^1.0.5",
        "debug": "^4.4.3",
        "http-errors": "^2.0.0",
        "iconv-lite": "^0.7.0",
        "on-finished": "^2.4.1",
        "qs": "^6.14.1",
        "raw-body": "^3.0.1",
        "type-is": "^2.0.1"
      },
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/bytes": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/call-bind-apply-helpers": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/call-bound": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "get-intrinsic": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/content-disposition": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/content-type": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/cookie": {
      "version": "0.7.2",
      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/cookie-signature": {
      "version": "1.2.2",
      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=6.6.0"
      }
    },
    "node_modules/cors": {
      "version": "2.8.6",
      "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "object-assign": "^4",
        "vary": "^1"
      },
      "engines": {
        "node": ">= 0.10"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/cross-spawn": {
      "version": "7.0.6",
      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "path-key": "^3.1.0",
        "shebang-command": "^2.0.0",
        "which": "^2.0.1"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/debug": {
      "version": "4.4.3",
      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ms": "^2.1.3"
      },
      "engines": {
        "node": ">=6.0"
      },
      "peerDependenciesMeta": {
        "supports-color": {
          "optional": true
        }
      }
    },
    "node_modules/depd": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/dunder-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.1",
        "es-errors": "^1.3.0",
        "gopd": "^1.2.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/ee-first": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/encodeurl": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/es-define-property": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-errors": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/es-object-atoms": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/esbuild": {
      "version": "0.27.3",
      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "hasInstallScript": true,
      "license": "MIT",
      "bin": {
        "esbuild": "bin/esbuild"
      },
      "engines": {
        "node": ">=18"
      },
      "optionalDependencies": {
        "@esbuild/aix-ppc64": "0.27.3",
        "@esbuild/android-arm": "0.27.3",
        "@esbuild/android-arm64": "0.27.3",
        "@esbuild/android-x64": "0.27.3",
        "@esbuild/darwin-arm64": "0.27.3",
        "@esbuild/darwin-x64": "0.27.3",
        "@esbuild/freebsd-arm64": "0.27.3",
        "@esbuild/freebsd-x64": "0.27.3",
        "@esbuild/linux-arm": "0.27.3",
        "@esbuild/linux-arm64": "0.27.3",
        "@esbuild/linux-ia32": "0.27.3",
        "@esbuild/linux-loong64": "0.27.3",
        "@esbuild/linux-mips64el": "0.27.3",
        "@esbuild/linux-ppc64": "0.27.3",
        "@esbuild/linux-riscv64": "0.27.3",
        "@esbuild/linux-s390x": "0.27.3",
        "@esbuild/linux-x64": "0.27.3",
        "@esbuild/netbsd-arm64": "0.27.3",
        "@esbuild/netbsd-x64": "0.27.3",
        "@esbuild/openbsd-arm64": "0.27.3",
        "@esbuild/openbsd-x64": "0.27.3",
        "@esbuild/openharmony-arm64": "0.27.3",
        "@esbuild/sunos-x64": "0.27.3",
        "@esbuild/win32-arm64": "0.27.3",
        "@esbuild/win32-ia32": "0.27.3",
        "@esbuild/win32-x64": "0.27.3"
      }
    },
    "node_modules/escape-html": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/etag": {
      "version": "1.8.1",
      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/eventsource": {
      "version": "3.0.7",
      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "eventsource-parser": "^3.0.1"
      },
      "engines": {
        "node": ">=18.0.0"
      }
    },
    "node_modules/eventsource-parser": {
      "version": "3.0.6",
      "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=18.0.0"
      }
    },
    "node_modules/express": {
      "version": "5.2.1",
      "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "accepts": "^2.0.0",
        "body-parser": "^2.2.1",
        "content-disposition": "^1.0.0",
        "content-type": "^1.0.5",
        "cookie": "^0.7.1",
        "cookie-signature": "^1.2.1",
        "debug": "^4.4.0",
        "depd": "^2.0.0",
        "encodeurl": "^2.0.0",
        "escape-html": "^1.0.3",
        "etag": "^1.8.1",
        "finalhandler": "^2.1.0",
        "fresh": "^2.0.0",
        "http-errors": "^2.0.0",
        "merge-descriptors": "^2.0.0",
        "mime-types": "^3.0.0",
        "on-finished": "^2.4.1",
        "once": "^1.4.0",
        "parseurl": "^1.3.3",
        "proxy-addr": "^2.0.7",
        "qs": "^6.14.0",
        "range-parser": "^1.2.1",
        "router": "^2.2.0",
        "send": "^1.1.0",
        "serve-static": "^2.2.0",
        "statuses": "^2.0.1",
        "type-is": "^2.0.1",
        "vary": "^1.1.2"
      },
      "engines": {
        "node": ">= 18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/express-rate-limit": {
      "version": "8.2.1",
      "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ip-address": "10.0.1"
      },
      "engines": {
        "node": ">= 16"
      },
      "funding": {
        "url": "https://github.com/sponsors/express-rate-limit"
      },
      "peerDependencies": {
        "express": ">= 4.11"
      }
    },
    "node_modules/fast-deep-equal": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/fast-uri": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/fastify"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/fastify"
        }
      ],
      "license": "BSD-3-Clause"
    },
    "node_modules/finalhandler": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "^4.4.0",
        "encodeurl": "^2.0.0",
        "escape-html": "^1.0.3",
        "on-finished": "^2.4.1",
        "parseurl": "^1.3.3",
        "statuses": "^2.0.1"
      },
      "engines": {
        "node": ">= 18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/forwarded": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/fresh": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/fsevents": {
      "version": "2.3.3",
      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "hasInstallScript": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
      }
    },
    "node_modules/function-bind": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-intrinsic": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bind-apply-helpers": "^1.0.2",
        "es-define-property": "^1.0.1",
        "es-errors": "^1.3.0",
        "es-object-atoms": "^1.1.1",
        "function-bind": "^1.1.2",
        "get-proto": "^1.0.1",
        "gopd": "^1.2.0",
        "has-symbols": "^1.1.0",
        "hasown": "^2.0.2",
        "math-intrinsics": "^1.1.0"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/get-proto": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "dunder-proto": "^1.0.1",
        "es-object-atoms": "^1.0.0"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/get-tsconfig": {
      "version": "4.13.6",
      "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "resolve-pkg-maps": "^1.0.0"
      },
      "funding": {
        "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
      }
    },
    "node_modules/gopd": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/has-symbols": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/hasown": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/hono": {
      "version": "4.11.9",
      "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.9.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=16.9.0"
      }
    },
    "node_modules/http-errors": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "depd": "~2.0.0",
        "inherits": "~2.0.4",
        "setprototypeof": "~1.2.0",
        "statuses": "~2.0.2",
        "toidentifier": "~1.0.1"
      },
      "engines": {
        "node": ">= 0.8"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/iconv-lite": {
      "version": "0.7.2",
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "safer-buffer": ">= 2.1.2 < 3.0.0"
      },
      "engines": {
        "node": ">=0.10.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/inherits": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/ip-address": {
      "version": "10.0.1",
      "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 12"
      }
    },
    "node_modules/ipaddr.js": {
      "version": "1.9.1",
      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/is-promise": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/isexe": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/jose": {
      "version": "6.1.3",
      "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/panva"
      }
    },
    "node_modules/json-schema-traverse": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/json-schema-typed": {
      "version": "8.0.2",
      "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-2-Clause"
    },
    "node_modules/math-intrinsics": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/media-typer": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/merge-descriptors": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/mime-db": {
      "version": "1.54.0",
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/mime-types": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "mime-db": "^1.54.0"
      },
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/ms": {
      "version": "2.1.3",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/negotiator": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/object-assign": {
      "version": "4.1.1",
      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/object-inspect": {
      "version": "1.13.4",
      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/on-finished": {
      "version": "2.4.1",
      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ee-first": "1.1.1"
      },
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/once": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "dependencies": {
        "wrappy": "1"
      }
    },
    "node_modules/parseurl": {
      "version": "1.3.3",
      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/path-key": {
      "version": "3.1.1",
      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/path-to-regexp": {
      "version": "8.3.0",
      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/pkce-challenge": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=16.20.0"
      }
    },
    "node_modules/proxy-addr": {
      "version": "2.0.7",
      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "forwarded": "0.2.0",
        "ipaddr.js": "1.9.1"
      },
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/qs": {
      "version": "6.15.0",
      "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause",
      "dependencies": {
        "side-channel": "^1.1.0"
      },
      "engines": {
        "node": ">=0.6"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/range-parser": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/raw-body": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "bytes": "~3.1.2",
        "http-errors": "~2.0.1",
        "iconv-lite": "~0.7.0",
        "unpipe": "~1.0.0"
      },
      "engines": {
        "node": ">= 0.10"
      }
    },
    "node_modules/require-from-string": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/resolve-pkg-maps": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "funding": {
        "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
      }
    },
    "node_modules/router": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "^4.4.0",
        "depd": "^2.0.0",
        "is-promise": "^4.0.0",
        "parseurl": "^1.3.3",
        "path-to-regexp": "^8.0.0"
      },
      "engines": {
        "node": ">= 18"
      }
    },
    "node_modules/safer-buffer": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/send": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "debug": "^4.4.3",
        "encodeurl": "^2.0.0",
        "escape-html": "^1.0.3",
        "etag": "^1.8.1",
        "fresh": "^2.0.0",
        "http-errors": "^2.0.1",
        "mime-types": "^3.0.2",
        "ms": "^2.1.3",
        "on-finished": "^2.4.1",
        "range-parser": "^1.2.1",
        "statuses": "^2.0.2"
      },
      "engines": {
        "node": ">= 18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/serve-static": {
      "version": "2.2.1",
      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "encodeurl": "^2.0.0",
        "escape-html": "^1.0.3",
        "parseurl": "^1.3.3",
        "send": "^1.2.0"
      },
      "engines": {
        "node": ">= 18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/express"
      }
    },
    "node_modules/setprototypeof": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/shebang-command": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "shebang-regex": "^3.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/shebang-regex": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/side-channel": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "object-inspect": "^1.13.3",
        "side-channel-list": "^1.0.0",
        "side-channel-map": "^1.0.1",
        "side-channel-weakmap": "^1.0.2"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-list": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es-errors": "^1.3.0",
        "object-inspect": "^1.13.3"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-map": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bound": "^1.0.2",
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.5",
        "object-inspect": "^1.13.3"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/side-channel-weakmap": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "call-bound": "^1.0.2",
        "es-errors": "^1.3.0",
        "get-intrinsic": "^1.2.5",
        "object-inspect": "^1.13.3",
        "side-channel-map": "^1.0.1"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/statuses": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/toidentifier": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.6"
      }
    },
    "node_modules/tsx": {
      "version": "4.21.0",
      "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "esbuild": "~0.27.0",
        "get-tsconfig": "^4.7.5"
      },
      "bin": {
        "tsx": "dist/cli.mjs"
      },
      "engines": {
        "node": ">=18.0.0"
      },
      "optionalDependencies": {
        "fsevents": "~2.3.3"
      }
    },
    "node_modules/type-is": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "content-type": "^1.0.5",
        "media-typer": "^1.1.0",
        "mime-types": "^3.0.0"
      },
      "engines": {
        "node": ">= 0.6"
      }
    },
    "node_modules/typescript": {
      "version": "5.9.3",
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "bin": {
        "tsc": "bin/tsc",
        "tsserver": "bin/tsserver"
      },
      "engines": {
        "node": ">=14.17"
      }
    },
    "node_modules/undici-types": {
      "version": "7.16.0",
      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/unpipe": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/vary": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.8"
      }
    },
    "node_modules/which": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "dependencies": {
        "isexe": "^2.0.0"
      },
      "bin": {
        "node-which": "bin/node-which"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/wrappy": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/zod": {
      "version": "4.3.6",
      "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/colinhacks"
      }
    },
    "node_modules/zod-to-json-schema": {
      "version": "3.25.1",
      "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "peerDependencies": {
        "zod": "^3.25 || ^4"
      }
    }
  }
}


path: scripts/tellermcp-server/package.json
content: {
  "name": "tellermcp",
  "version": "1.0.0",
  "description": "Model Context Protocol server exposing Teller delta-neutral and lending APIs",
  "type": "module",
  "scripts": {
    "start": "tsx src/index.ts",
    "dev": "tsx watch src/index.ts",
    "build": "tsc -p ."
  },
  "keywords": ["teller", "mcp", "delta-neutral", "lending"],
  "author": "",
  "license": "MIT",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.26.0",
    "zod": "^4.3.6"
  },
  "devDependencies": {
    "@types/node": "^25.2.3",
    "tsx": "^4.21.0",
    "typescript": "^5.9.3"
  }
}


path: scripts/tellermcp-server/src/client.ts
content: import type {
  BorrowGeneralResponse,
  BorrowTerms,
  BorrowTransactionsResponse,
  DeltaNeutralOpportunityResponse,
  LoansResponse,
  RepayTransactionsResponse
} from './types.js';

export interface TellerApiClientOptions {
  baseUrl?: string;
  timeoutMs?: number;
}

const DEFAULT_BASE_URL = process.env.TELLER_API_BASE_URL?.trim() || 'https://delta-neutral-api.teller.org';
const DEFAULT_TIMEOUT_MS = Number(process.env.TELLER_API_TIMEOUT_MS ?? 15_000);

export class TellerApiClient {
  private readonly baseUrl: string;
  private readonly timeoutMs: number;

  constructor(options: TellerApiClientOptions = {}) {
    this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
    this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
  }

  async getDeltaNeutralOpportunities(params?: { chainId?: number; coin?: string; limit?: number; minNetAprPct?: number }): Promise<DeltaNeutralOpportunityResponse> {
    const response = await this.request<DeltaNeutralOpportunityResponse>('/perps/delta-neutral');

    const filtered = response.opportunities.filter(opportunity => {
      const matchesChain = params?.chainId ? opportunity.chainId === params.chainId : true;
      const matchesCoin = params?.coin ? opportunity.coin.toLowerCase() === params.coin.toLowerCase() : true;
      const matchesApr = params?.minNetAprPct !== undefined ? opportunity.netAprPct >= params.minNetAprPct : true;
      return matchesChain && matchesCoin && matchesApr;
    });

    const limited = params?.limit ? filtered.slice(0, params.limit) : filtered;

    return {
      ...response,
      count: limited.length,
      opportunities: limited
    };
  }

  getBorrowPools(query?: {
    chainId?: number;
    collateralTokenAddress?: string;
    borrowTokenAddress?: string;
    poolAddress?: string;
    ttl?: number;
  }): Promise<BorrowGeneralResponse> {
    return this.request<BorrowGeneralResponse>('/borrow/general', {
      chainId: query?.chainId,
      collateral_token_address: query?.collateralTokenAddress,
      borrow_token_address: query?.borrowTokenAddress,
      pool_address: query?.poolAddress,
      ttl: query?.ttl
    });
  }

  getBorrowTerms(params: { wallet: string; chainId: number; collateralToken: string; poolAddress: string }): Promise<BorrowTerms> {
    return this.request<BorrowTerms>('/borrow-terms', {
      wallet: params.wallet,
      chainId: params.chainId,
      collateralToken: params.collateralToken,
      poolAddress: params.poolAddress
    });
  }

  getBorrowTransactions(params: {
    walletAddress: string;
    collateralTokenAddress: string;
    chainId: number;
    poolAddress: string;
    collateralAmount: string;
    principalAmount: string;
    loanDuration?: number;
  }): Promise<BorrowTransactionsResponse> {
    return this.request<BorrowTransactionsResponse>('/borrow-tx', {
      walletAddress: params.walletAddress,
      collateralTokenAddress: params.collateralTokenAddress,
      chainId: params.chainId,
      poolAddress: params.poolAddress,
      collateralAmount: params.collateralAmount,
      principalAmount: params.principalAmount,
      loanDuration: params.loanDuration
    });
  }

  getLoans(params: { walletAddress: string; chainId: number }): Promise<LoansResponse> {
    return this.request<LoansResponse>('/loans/get-all', {
      walletAddress: params.walletAddress,
      chainId: params.chainId
    });
  }

  getRepayTransactions(params: { bidId: number; chainId: number; walletAddress: string; amount?: string }): Promise<RepayTransactionsResponse> {
    return this.request<RepayTransactionsResponse>('/loans/repay-tx', {
      bidId: params.bidId,
      chainId: params.chainId,
      walletAddress: params.walletAddress,
      amount: params.amount
    });
  }

  private async request<T>(path: string, query?: Record<string, string | number | boolean | undefined>): Promise<T> {
    const url = new URL(path, this.baseUrl);
    if (query) {
      for (const [key, value] of Object.entries(query)) {
        if (value === undefined || value === null || value === '') continue;
        url.searchParams.set(key, String(value));
      }
    }

    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), this.timeoutMs);

    try {
      const response = await fetch(url, {
        signal: controller.signal,
        headers: {
          'accept': 'application/json'
        }
      });

      if (!response.ok) {
        const body = await response.text();
        throw new Error(`Request failed with ${response.status}: ${body}`);
      }

      return (await response.json()) as T;
    } catch (error) {
      if ((error as Error).name === 'AbortError') {
        throw new Error(`Request timed out after ${this.timeoutMs}ms`);
      }
      throw error;
    } finally {
      clearTimeout(timeout);
    }
  }
}


path: scripts/tellermcp-server/src/index.ts
content: import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import * as z from 'zod';
import { TellerApiClient } from './client.js';

const server = new McpServer({
  name: 'tellermcp',
  version: '0.1.0',
  description: 'Expose Teller delta-neutral and lending workflows via MCP tools'
});

const client = new TellerApiClient();

const jsonResponse = (summary: string, data: unknown) => ({
  content: [
    {
      type: 'text' as const,
      text: summary
    }
  ],
  structuredContent: {
    payload: data
  }
});

server.registerTool(
  'get-delta-neutral-opportunities',
  {
    description: 'List delta-neutral arbitrage opportunities from Teller perps endpoint',
    inputSchema: z
      .object({
        chainId: z
          .number()
          .describe('Chain ID to filter opportunities')
          .int()
          .positive()
          .optional(),
        coin: z
          .string()
          .describe('Token symbol to filter (e.g., ETH, ARB)')
          .trim()
          .transform(value => value.toUpperCase())
          .optional(),
        limit: z
          .number()
          .describe('Maximum number of opportunities to return')
          .int()
          .min(1)
          .max(50)
          .optional(),
        minNetAprPct: z
          .number()
          .describe('Minimum net APR percentage to include')
          .optional()
      })
      .optional()
  },
  async input => {
    const data = await client.getDeltaNeutralOpportunities({
      chainId: input?.chainId,
      coin: input?.coin,
      limit: input?.limit,
      minNetAprPct: input?.minNetAprPct
    });
    const count = data.count ?? data.opportunities.length;
    return jsonResponse(`Returned ${count} delta-neutral opportunit${count === 1 ? 'y' : 'ies'}.`, data);
  }
);

server.registerTool(
  'get-borrow-pools',
  {
    description: 'Get Teller borrow pools with optional filters',
    inputSchema: z
      .object({
        chainId: z.number().int().positive().optional(),
        collateralTokenAddress: z
          .string()
          .trim()
          .regex(/^0x[a-fA-F0-9]{40}$/u, 'Must be a valid address')
          .optional(),
        borrowTokenAddress: z
          .string()
          .trim()
          .regex(/^0x[a-fA-F0-9]{40}$/u, 'Must be a valid address')
          .optional(),
        poolAddress: z
          .string()
          .trim()
          .regex(/^0x[a-fA-F0-9]{40}$/u, 'Must be a valid address')
          .optional(),
        ttl: z
          .number()
          .describe('Cache TTL override in seconds')
          .int()
          .min(60)
          .max(86_400)
          .optional()
      })
      .optional()
  },
  async input => {
    const data = await client.getBorrowPools({
      chainId: input?.chainId,
      collateralTokenAddress: input?.collateralTokenAddress,
      borrowTokenAddress: input?.borrowTokenAddress,
      poolAddress: input?.poolAddress,
      ttl: input?.ttl
    });
    return jsonResponse(`Returned ${data.count} borrow pool${data.count === 1 ? '' : 's'}.`, data);
  }
);

server.registerTool(
  'get-borrow-terms',
  {
    description: 'Calculate borrow terms for a specific wallet, collateral token, and pool',
    inputSchema: z.object({
      wallet: z
        .string()
        .trim()
        .regex(/^0x[a-fA-F0-9]{40}$/u, 'Wallet must be a valid address'),
      chainId: z.number().int().positive(),
      collateralToken: z
        .string()
        .trim()
        .regex(/^0x[a-fA-F0-9]{40}$/u, 'Collateral token must be a valid address'),
      poolAddress: z
        .string()
        .trim()
        .regex(/^0x[a-fA-F0-9]{40}$/u, 'Pool address must be valid')
    })
  },
  async ({ wallet, chainId, collateralToken, poolAddress }) => {
    const data = await client.getBorrowTerms({ wallet, chainId, collateralToken, poolAddress });
    const maxUsd = typeof data.maxBorrowUsd === 'number' ? data.maxBorrowUsd.toFixed(2) : 'unknown';
    return jsonResponse(`Borrow terms ready — est. max borrow ${maxUsd} USD.`, data);
  }
);

server.registerTool(
  'build-borrow-transactions',
  {
    description: 'Return encoded transactions required to borrow from a Teller pool',
    inputSchema: z.object({
      walletAddress: z
        .string()
        .trim()
        .regex(/^0x[a-fA-F0-9]{40}$/u, 'Wallet must be a valid address'),
      collateralTokenAddress: z
        .string()
        .trim()
        .regex(/^0x[a-fA-F0-9]{40}$/u, 'Collateral token must be valid'),
      chainId: z.number().int().positive(),
      poolAddress: z
        .string()
        .trim()
        .regex(/^0x[a-fA-F0-9]{40}$/u, 'Pool address must be valid'),
      collateralAmount: z
        .string()
        .min(1, 'Provide the collateral amount in wei/base units'),
      principalAmount: z
        .string()
        .min(1, 'Provide the principal amount in wei/base units'),
      loanDuration: z
        .number()
        .describe('Loan duration in seconds (defaults to 30 days if omitted)')
        .int()
        .positive()
        .optional()
    })
  },
  async input => {
    const data = await client.getBorrowTransactions(input);
    return jsonResponse(
      `Prepared ${data.summary.totalTransactions} borrow transaction${data.summary.totalTransactions === 1 ? '' : 's'}.`,
      data
    );
  }
);

server.registerTool(
  'get-wallet-loans',
  {
    description: 'List active and historical Teller loans for a wallet',
    inputSchema: z.object({
      walletAddress: z
        .string()
        .trim()
        .regex(/^0x[a-fA-F0-9]{40}$/u, 'Wallet must be a valid address'),
      chainId: z.number().int().positive()
    })
  },
  async ({ walletAddress, chainId }) => {
    const data = await client.getLoans({ walletAddress, chainId });
    return jsonResponse(`Found ${data.count} loan${data.count === 1 ? '' : 's'} for this wallet.`, data);
  }
);

server.registerTool(
  'build-repay-transactions',
  {
    description: 'Build repayment approval + repay transactions for a Teller loan',
    inputSchema: z.object({
      bidId: z.number().int().nonnegative(),
      chainId: z.number().int().positive(),
      walletAddress: z
        .string()
        .trim()
        .regex(/^0x[a-fA-F0-9]{40}$/u, 'Wallet must be a valid address'),
      amount: z
        .string()
        .min(1, 'Optional partial repayment amount in wei')
        .optional()
    })
  },
  async ({ bidId, chainId, walletAddress, amount }) => {
    const data = await client.getRepayTransactions({ bidId, chainId, walletAddress, amount });
    const detail = data.summary.isFullRepayment ? 'full repayment' : 'partial repayment';
    return jsonResponse(`Prepared ${detail} transactions for loan #${data.summary.loanId}.`, data);
  }
);

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('tellermcp MCP server listening on stdio');
}

main().catch(error => {
  console.error('tellermcp server error:', error);
  process.exit(1);
});


path: scripts/tellermcp-server/src/types.ts
content: export interface DeltaNeutralOpportunityResponse {
  ok: boolean;
  asOf: string;
  count: number;
  opportunities: DeltaNeutralOpportunity[];
}

export interface DeltaNeutralOpportunity {
  chainId: number;
  coin: string;
  poolAddress: string;
  platformUrl: string;
  platformLogo?: string | null;
  fundingAprYearlyPct: number;
  fundingAprAbsPct: number;
  borrowAprPct: number;
  borrowFeePct: {
    marketplaceFeePct: number;
    protocolFeePct: number;
    totalBorrowFeePct: number;
  };
  netAprPct: number;
  principalAvailable: string;
  principalAvailableUsd: number;
  allPlatforms: PlatformFundingData[];
  raw?: unknown;
}

export interface PlatformFundingData {
  platformUrl: string;
  platformLogo?: string | null;
  fundingAprYearlyPct: number;
  fundingAprAbsPct: number;
  fundingRate8h?: number | null;
  fundingRateHourly?: number | null;
  oraclePx?: number | null;
  openInterest?: number | null;
}

export interface BorrowGeneralResponse {
  updated_at: number;
  ttl_ms: number;
  count: number;
  filters: Record<string, unknown>;
  results: BorrowPool[];
}

export interface BorrowPool {
  chainId: number;
  pool_address: string;
  collateral_token_address: string;
  collateral_token_symbol: string;
  borrow_token_address: string;
  borrow_token_symbol: string;
  active: boolean;
  isV2?: boolean;
  enrichment?: {
    marketId?: number;
    marketplaceFeePercent?: number | null;
    paymentCycleDuration?: number | null;
    collateralRatioBps?: number;
    collateralRatioPct?: number;
    principalToken?: string;
    principalTokenDecimals?: number;
    minInterestRateBps?: number;
    minInterestRatePct?: number;
    principalAvailableRaw?: string;
    principalAvailable?: number;
    principalAvailableUsd?: number | null;
  };
  enrichmentError?: string;
}

export interface BorrowTerms {
  wallet: string;
  chainId: number;
  collateralToken: string;
  collateralTokenSymbol: string;
  poolAddress: string;
  borrowToken: string;
  borrowTokenSymbol: string;
  collateralWalletBalance?: number;
  collateralWalletBalanceUsd?: number | null;
  collateralSuppliedTokens?: number;
  collateralSuppliedUsd?: number;
  collateralTotalUsd?: number;
  ltvPct?: number;
  collateralRatioPct?: number;
  collateralRatioBps?: number;
  minInterestRatePct?: number;
  minInterestRateBps?: number;
  marketplaceFeePercent?: number;
  paymentCycleDuration?: number;
  paymentCycleDurationYears?: number;
  termInterestPct?: number;
  aprPct?: number;
  principalAvailable?: string;
  principalAvailableUsd?: number;
  maxBorrowByCollateral?: number;
  maxBorrowUsd?: number;
  maxCollateralNeededUsd?: number;
  maxCollateralAmount?: number | null;
  collateralPrice?: number | null;
  marketId?: string;
  principalToken?: string;
  principalTokenDecimals?: number;
  isV2?: boolean;
  poolVersion?: string;
  error?: string;
}

export interface BorrowTransactionsResponse {
  transactions: Array<{
    to: string;
    data: string;
    functionName: string;
    args: Array<string | number>;
    description: string;
    value: string;
  }>;
  summary: {
    totalTransactions: number;
    needsApproval: boolean;
    needsForwarderApproval: boolean;
    needsZeroAllowance: boolean;
    [key: string]: unknown;
  };
}

export interface LoansResponse {
  walletAddress: string;
  chainId: number;
  count: number;
  loans: Loan[];
}

export interface Loan {
  bidId: string;
  borrowerAddress: string;
  lenderAddress: string;
  lendingTokenAddress: string;
  principal: string;
  status: string;
  apr?: string;
  loanDuration?: string;
  paymentCycle?: string;
  paymentCycleAmount?: string;
  acceptedTimestamp?: string;
  nextDueDate?: string;
  collateral?: unknown;
  marketplace?: unknown;
  [key: string]: unknown;
}

export interface RepayTransactionsResponse {
  transactions: Array<{
    to: string;
    data: string;
    functionName: string;
    args: Array<string | number>;
    description: string;
    value: string;
  }>;
  summary: {
    totalTransactions: number;
    loanId: number;
    repaymentAmount: string;
    isFullRepayment: boolean;
    lendingToken?: string;
    [key: string]: unknown;
  };
}


path: scripts/tellermcp-server/tsconfig.json
content: {
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Node",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true,
    "strict": true,
    "resolveJsonModule": true,
    "outDir": "dist",
    "types": ["node"]
  },
  "include": ["src"]
}


Security scan verdicts — ClawScan: clean | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)