Help us shape the future of Go! Take the 2026 Go Developer Survey

newapi-operator

module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2026 License: MIT

README

newapi-operator

CI Go Reference Latest release License

English | 中文

An MCP server that gives an AI agent full administrative control over a self-hosted New API LLM gateway: channels, downstream keys, users, quota, pricing and usage logs — plus a pass-through to every other admin route the running release exposes.

AI agent  ◄── MCP (stdio / HTTP) ──►  newapi-operator  ◄── /api/* ──►  New API

47 curated tools · 312-route pass-through · route table generated from upstream source, with a weekly drift check.

Quickstart

Requires Go 1.26 or newer.

git clone https://github.com/Ruanyuxi1337/newapi-operator.git
cd newapi-operator
make build

Or install just the server binary with Go (Go 1.26+):

go install github.com/Ruanyuxi1337/newapi-operator/cmd/newapi-operator@latest

Create an access token in New API: avatar → Personal settings → Generate access token.

Use an access token, not a relay key (sk-…) and not your password. New API allows one session per user, so a password login from a script returns 409 while the panel is open in a browser.

Register the binary with any MCP client that speaks stdio:

{
  "mcpServers": {
    "newapi": {
      "command": "/absolute/path/to/bin/newapi-operator",
      "env": {
        "NEWAPI_BASE_URL": "http://127.0.0.1:3001",
        "NEWAPI_ACCESS_TOKEN": "nap_…",
        "NEWAPI_USER_ID": "1"
      }
    }
  }
}

Restart the client and ask the agent for user_session_info. It returns the running New API version and feature flags — the fastest way to confirm the base URL and token are right.

What the wrapper fixes

New API's admin API is not plain REST. These are the contracts a naive client gets wrong, and the reason the curated tools exist:

Contract A naive client
Rejections return HTTP 200 with {"success": false} Treats every error as success
Channel creation expects a nested {"mode": …, "channel": {…}} body Sends a flat body and is rejected
Updates use PUT /api/channel with the id in the body Calls PUT /api/channel/:id and gets 404
models and model_mapping are strings Sends arrays and is rejected
OpenAI channel base_url must not end in /v1 Requests hit /v1/v1/chat/completions and 404
Quota uses internal units (500,000 = $1) Spend caps are off by 500,000×

The server turns success: false into a tool error, so a returned payload always means the call actually worked.

Configuration

Variable Required Default Purpose
NEWAPI_BASE_URL yes — Instance origin, e.g. http://127.0.0.1:3001. Trailing / and /api are stripped.
NEWAPI_ACCESS_TOKEN yes — Admin access token.
NEWAPI_USER_ID no 1 Sent as New-Api-User; must be the token owner's numeric id.
NEWAPI_TIMEOUT no 60s Per-request timeout.
NEWAPI_READ_ONLY no false Refuse every mutating tool.
NEWAPI_QUOTA_PER_UNIT no 500000 Quota units per currency unit, used by *_usd arguments.
MCP_TRANSPORT no stdio stdio or http.
MCP_HTTP_ADDR no 127.0.0.1:8080 Listener for the HTTP transport.
MCP_HTTP_TOKEN http only — Bearer token required on /mcp.
LOG_LEVEL no info debug, info, warn, error.
LOG_FORMAT no text text or json.

Startup fails fast when a required value is missing or the base URL, timeout or transport is invalid.

Call the gateway port directly, not a public domain. Reverse proxies that normalise trailing slashes answer 307 and drop the request body, which breaks every create and update call.

Tools

Area Count Tools
Channels 22 channel_list, channel_create, channel_test, channel_balance, channel_priority_reorder, channel_upstream_apply, channel_multi_key, …
Downstream keys 9 token_list, token_create, token_update, token_reveal_key, token_batch_keys, …
Users 6 user_list, user_manage, user_session_info, user_access_tokens, …
Settings, pricing, logs 7 option_list, option_set, pricing_get, pricing_patch, log_list, log_stats, …
Generic 3 api_request, api_endpoints, api_coverage

Full argument reference: docs/TOOLS.md.

The escape hatch

api_request calls any /api/* route, including the parts with no dedicated tool: subscriptions, deployments, task plugins, performance diagnostics, Ollama pulls. Discover the path first:

api_endpoints {"group": "subscription"}
→ GET   /api/subscription/plans
  POST  /api/subscription/admin/plans
  PATCH /api/subscription/admin/plans/:id

Substitute path parameters before calling, e.g. /api/channel/:id → /api/channel/7.

Staying current with New API

The route table lives in internal/spec/routes_gen.go and is generated — never hand-edited.

make sync                              # regenerate from the newest release
./bin/routesync --tag latest --report  # per-group route counts
./bin/routesync --tag latest --check   # exit 1 if the table has drifted

routesync reads router/*.go at the target tag and handles all three registration styles New API mixes:

channelRoute.GET("/test/:id", handler)                       // direct
handlePermissionRoute(channelRoute, "GET", "/ops", perm, h)   // helper, often wrapped
var channelPermissionRoutes = []permissionRoute{              // table-driven — most CRUD
    {method: http.MethodGet, path: "/priority/order", ...},
}

A parser that only understands the first style misses most of the admin surface; internal/spec covers all three, with tests for each.

To adopt a new release:

make sync && make sync-baseline
git diff internal/spec     # see exactly what upstream added or removed
go test ./...

A weekly workflow opens an issue when the committed table falls behind the latest release.

Deployment

stdio

The default. Your MCP client starts the binary; all logging goes to stderr so it never corrupts the protocol stream.

HTTP
NEWAPI_BASE_URL=http://127.0.0.1:3001 \
NEWAPI_ACCESS_TOKEN=… \
MCP_TRANSPORT=http MCP_HTTP_ADDR=127.0.0.1:8080 \
MCP_HTTP_TOKEN=$(openssl rand -hex 16) \
  ./bin/newapi-operator

POST /mcp requires Authorization: Bearer $MCP_HTTP_TOKEN. GET /healthz is unauthenticated and reports the binary version and route-table version.

Docker
docker build -t newapi-operator .

docker run --rm --network host \
  -e NEWAPI_BASE_URL=http://127.0.0.1:3001 \
  -e NEWAPI_ACCESS_TOKEN=… \
  -e MCP_TRANSPORT=http \
  -e MCP_HTTP_ADDR=0.0.0.0:8080 \
  -e MCP_HTTP_TOKEN=$(openssl rand -hex 16) \
  newapi-operator

--network host is Linux-only. Elsewhere, point NEWAPI_BASE_URL at a host the container can reach and publish port 8080.

Security model

  • Read-only mode (NEWAPI_READ_ONLY=true) refuses mutating tools at the registry layer, before a request is built.
  • Path allowlist — the client refuses paths outside /api/*, so the server cannot become an open proxy for relay traffic.
  • Credential redaction — internal/redact scrubs bearer tokens, sk-* keys, JWTs and secret-shaped JSON fields before they reach a log line or an error returned to the agent.
  • No ambient egress — the only host contacted is NEWAPI_BASE_URL. No telemetry, no listener unless you set MCP_TRANSPORT=http.
  • Delete is not disable — deleting a channel or token is irreversible; tool descriptions say so, and the agent instructions repeat it.

See SECURITY.md for reporting a vulnerability.

Development

make build      # build both binaries
make test       # go test ./... -race
make vet        # go vet ./...
make fmt        # gofmt
make sync       # regenerate the route table from the latest release
make smoke      # stdio end-to-end check against a live instance
cmd/newapi-operator/   MCP server
cmd/routesync/         route-table generator and drift detector
internal/client/       admin HTTP client (envelope, errors, redaction)
internal/config/       environment configuration
internal/redact/       credential scrubbing
internal/spec/         route table, upstream parser, generated routes
internal/tools/        curated and generic tools
docs/                  tool reference and design notes

See CONTRIBUTING.md before opening a PR and docs/ARCHITECTURE.md for how the pieces fit together.

License

MIT — see LICENSE. Not affiliated with the New API project; this is an independent client for its admin API.

Directories

Path Synopsis
cmd
newapi-operator command
Command newapi-operator is an MCP server that gives an AI agent full administrative control over a self-hosted New API LLM gateway.
Command newapi-operator is an MCP server that gives an AI agent full administrative control over a self-hosted New API LLM gateway.
routesync command
Command routesync regenerates the embedded New API route table from upstream router source, and detects drift between what this server knows and what a given New API release actually exposes.
Command routesync regenerates the embedded New API route table from upstream router source, and detects drift between what this server knows and what a given New API release actually exposes.
internal
client
Package client is a thin, strict HTTP client for the New API admin surface.
Package client is a thin, strict HTTP client for the New API admin surface.
config
Package config loads and validates runtime configuration from the environment.
Package config loads and validates runtime configuration from the environment.
redact
Package redact scrubs credential-shaped substrings out of anything that can reach a log line, an MCP tool result, or an error string.
Package redact scrubs credential-shaped substrings out of anything that can reach a log line, an MCP tool result, or an error string.
spec
Package spec holds the New API route table and the parser that derives it from upstream router source.
Package spec holds the New API route table and the parser that derives it from upstream router source.
tools
Package tools defines the MCP tool surface exposed to the agent.
Package tools defines the MCP tool surface exposed to the agent.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL