Skip to the content.

Architecture

The codebase is intentionally small, explicit, and grouped by API resource so it is easy to maintain and to regenerate when the upstream API evolves.

Layout

src/
  config.ts        Env -> validated Config (throws ConfigError).
  logger.ts        Leveled logger; writes to stderr only.
  errors.ts        Typed API errors mapped from HTTP status.
  rate-limiter.ts  Sliding-window limiter (~55/min).
  client.ts        HTTP client: auth header, rate limit, retry/backoff, error mapping.
  server.ts        Builds the McpServer and registers tools.
  index.ts         Programmatic exports.
  cli.ts           Executable entry (serve | login | ping | list-tools).
  tools/
    types.ts       ToolDefinition, defineTool(), ToolContext.
    helpers.ts     Shared Zod fragments + result helpers.
    registry.ts    Read-only + write-confirmation policy; error -> result mapping.
    index.ts       allTools[] — the implemented surface.
    <domain>.ts    One module per API tag.
tests/             Vitest unit tests (mock fetch / fake client; virtual clock).
scripts/           docs + spec-fingerprint generators.
docs/              This site.
openapi-specs/     fingerprint.json — derived metadata of the upstream OpenAPI doc
                   (the verbatim spec is third-party IP and is not committed).

Request lifecycle

MCP host
  │  tool call (name, args)
  ▼
registry wrapper ── Zod validate ──► read-only? ──► confirm gate (writes)
  │                                                      │
  ▼                                                      ▼
tool.handler(args, ctx)                         preview result (no API call)
  │
  ▼
RentecClient.get/post ── rate limit ── retry/backoff ── error mapping
  │
  ▼
Rentec Direct API ──► jsonResult(...)  |  typed error ──► isError result

Key design choices

Adding a tool

See the step-by-step guide in CLAUDE.md and Maintaining the Server.