tkflyc-ai-cli MCP server
Commit 14. Nov. 2026Starte lokale AI CLIs und OpenAI-kompatible APIs als MCP tools mit Support für Background Jobs und persistentes State Management.
Auch bekannt als moerasermax/tkflyc-ai-cli
- Stars
- 7
- Tools
- —
- Downloads, 30 Tage
- —
- Neueste Version
- —
- Letzter Commit
- 14. Nov. 2026
- Lizenz
- Apache-2.0
Was ist tkflyc-ai-cli MCP?
tkflyc-ai-cli ist ein MCP server. Starte lokale AI CLIs und OpenAI-kompatible APIs als MCP tools mit Support für Background Jobs und persistentes State Management.
Zusammenfassung generiert aus dem README des Projekts
Über tkflyc-ai-cli MCP server
Entwickler können lokale AI Command-Line Interfaces und OpenAI-kompatible APIs direkt über einen MCP Client ausführen. Dieser Server verwandelt Tools wie Claude, Codex, Grok und Windows Antigravity in zugängliche MCP tools. Er ist für User konzipiert, die komplexe Agent Loops benötigen, bei denen das Modell Dateioperationen durchführen und Bash-Commands ausführen kann.
Im Gegensatz zu einfachen Completion-Wrappern unterstützt dieses System Background Jobs mit durable State Management. Sobald ein Task gestartet wird, gibt das run tool sofort eine PID zurück, sodass du list_processes, peek, wait und get_result nutzen kannst, um den Fortschritt zu überwachen. Langlaufende Tasks werden über einen JobStore verwaltet, der abgeschlossene Jobs für 30 Minuten speichert.
Das Setup erfolgt durch das Hinzufügen des Servers zu einem Client wie Claude Code via npx oder durch das Ausführen der verteilten Dateien aus einer lokalen Source-Installation. Für Drittanbieter-Services kannst du Provider in einer JSON Datei konfigurieren, um Verbindungen zu OpenRouter, DeepSeek, Ollama oder NVIDIA hosted Endpoints herzustellen. Der Server übernimmt komplexe Anforderungen wie Exponential Backoff für rate-limited APIs und das Replay von Reasoning-Content für spezifische Modelle.
Was du damit machen kannst
- 1Background AI Tasks überwachenVerfolge den Fortschritt eines langlaufenden Coding-Tasks, indem du die Prozess-ID beobachtest.
- 2Eigene API Endpoints anbindenIntegriere jeden OpenAI-kompatiblen Service wie DeepSeek oder eine lokale Ollama Instanz in deinen AI Workflow.
- 3Full Agent Loops ausführenErmögliche einem AI Modell die Interaktion mit deinem lokalen System durch das Lesen von Dateien und das Ausführen von Commands.
- 4API Rate Limits verwaltenStelle zuverlässige Verbindungen zu geteilten Endpoints sicher, die häufig 429 oder 5xx Fehler zurückgeben.
Geschrieben aus dem README des Projekts. Jeder Use Case wurde gegen ein Zitat daraus geprüft.
Automatisierte Checks
Geluften am 15. Nov. 2026Vollständiger Bericht →Noch nicht verifiziert. Ein Server benötigt einen Score von 80, keine kritischen Befunde und genug Daten für unsere Prüfung. Wie die Checks funktionieren · Was du für mehr Punkte verbessern kannst
- Source Repository verknüpft und erreichbarmoerasermax/tkflyc-ai-cli is public and reachablegithub.com/moerasermax/tkflyc-ai-cli ↗Bestanden
- Paket nennt dieses Repository als QuelleNicht geprüft
- Build-Provenienz (Sigstore-Attestierung)Nicht geprüft
- Open Source Lizenz (OSI)Apache-2.0spdx.org/licenses/Apache-2.0.html ↗Bestanden
- Commit oder Release im letzten JahrLast commit or release 2026-11-13github.com/moerasermax/tkflyc-ai-cli ↗Bestanden
- OpenSSF ScorecardNicht geprüft
- Package-Name ähnelt keinem populären PackageNicht geprüft
- Keine kritischen Advisories im Paket oder seinen AbhängigkeitenNicht geprüft
- Keine versteckten Anweisungen an das Modell0 tool descriptions and the README read; no override phrases, credential paths or hidden charactersBestanden
- Destruktive Tools sind markiertNicht geprüft
- Remote-Endpoint beantwortet den MCP-HandshakeNicht geprüft
README
Auf GitHub ansehenai-cli-mcp
Optional ai-cli_kernel_panel: /kernel opens the dashboard in a new Terminal tab; /kernel side opens an embedded session pane with two-step confirmation.
Run local AI CLIs — Claude, Codex, Grok, Antigravity (agy) — and any third-party
OpenAI-compatible API as MCP tools, with background jobs. Self-maintained from
source, built on a registry architecture: adding an agent means adding one file.
Requires Node ^20.19.0 || >=22.12.0.
完整中文文件(環境變數、設定檔、每個工具的細節)見 README.zh-TW.md. The Chinese document is the exhaustive reference; this page covers the design and the parts you need to get running.
What it does
Each supported CLI becomes a tool you can call from an MCP client. Jobs run in the
background: run returns a PID immediately, and list_processes, peek, wait and
get_result observe it while it works. Two surfaces expose this — the MCP server and
the ai-cli command line — sharing durable state for Claude, Codex, Grok and Windows Antigravity.
Quick start
From npm — nothing to build:
claude mcp add ai-cli -s user -- npx -y @tkflyc/ai-cli-mcp
From source — if you intend to change it, or want auto-update:
git clone https://github.com/moerasermax/tkflyc-ai-cli
cd tkflyc-ai-cli
npm install # triggers build via the prepare script and produces dist/
claude mcp add ai-cli -s user -- node "$PWD/dist/server.js"
dist/ is not version-controlled, so the source install has to build before first
use. npm install runs it through the prepare script, so a separate
npm run build is normally unnecessary.
⚠️ The two paths differ in more than building. Auto-update requires a clone with
.git and package.json (see Auto-update below), so an npm/npx install never
updates itself — moving to a new version is something you do yourself. Pin the
version in the command (@tkflyc/ai-cli-mcp@<version>) if you need to know exactly
which one is running.
doctor reports whether this installation meets the source-update precondition
in update.supported.
Wiring into Claude Code
# bash / git bash
claude mcp add ai-cli -s user -- node "$PWD/dist/server.js"
# PowerShell
claude mcp add ai-cli -s user -- node "$PWD\dist\server.js"
Agents
Usage notes for each backend. Maintainer acceptance procedures are in tools/acceptance/README.md.
Grok CLI
Grok is a separate xAI CLI backend for coding and text work. Select grok-4.7,
grok-4.7-build-fast, grok-4.6, or grok-4.5; models and ai-cli models
query grok models with a 15-second timeout and retain successful cache values or
label the builtin fallback on failure (including an unauthenticated CLI).
GROK_CLI_NAME overrides the binary; otherwise PATH wins, with
~/.grok/bin/grok.exe (Windows) or ~/.grok/bin/grok as fallback. Doctor lists Grok.
Prompts use --prompt-file to preserve long Windows prompts. Native Windows
execution bypasses cmd.exe; --rules receives the shared WORKER_CONTEXT first,
then an optional run.system_prompt, separated by a blank line. Every resume
reinjects the lock with --resume; --no-subagents is always set. Normal mode
uses --always-approve. reasoning_effort accepts only low, medium, high, xhigh (live verified: grok 1.0.50).
Grok results with subtype: error_during_execution or stop_reason: cancelled
fail even with exit 0; the error includes both fields.
Grok uses the same durable JobStore/runner, restart recovery and 30-minute finished
job retention as Claude/Codex. Messages JSON result usage includes cache tokens in
normalized input and exposes cost_usd_nominal (vendor estimate, not a billing statement).
The strict read-only capabilities flags, their live verification and the F2 live-verification checklist are maintainer acceptance steps; see tools/acceptance/README.md. Empty and unsupported capabilities are refused.
Antigravity model list
Antigravity's top-level model list uses routable vendor results (including successful
cached results) plus agy / agy-default. Without a usable result, its fallback is
agy, agy-default, gemini-3.1-pro-high, and gemini-3.8-flash-high.
direct-api
Besides the three local CLIs there is a fourth path that starts no subprocess at all:
direct-api talks HTTP from inside the Node process, so any OpenAI-compatible
/chat/completions endpoint works — OpenRouter, DashScope, DeepSeek, NVIDIA's
hosted NIM catalog, a local Ollama, your company gateway. Adding a provider needs no
code change, only a config entry.
It is not a thin completion wrapper: it runs the full agent loop, so the model gets
read_file / write_file / bash and can actually change files and run commands.
Configuring a provider
~/.local/share/ai-cli/providers.json (override with AI_CLI_PROVIDERS_PATH):
{
"providers": {
"openrouter": { "api_key": "sk-or-v1-..." },
"local": { "base_url": "http://127.0.0.1:11434/v1", "api_key": "ollama" },
"nv": {
"base_url": "https://integrate.api.nvidia.com/v1",
"api_key": "nvapi-...",
"retry": { "max_retries": 3, "initial_delay_ms": 1000 },
"extra_body": { "max_tokens": 8192 },
"model_extra_body": {
"nvidia/nemotron-3.5-lightning-30b-a3b": { "reasoning_effort": "none" }
}
}
}
}
Address a model as <provider>-<model>, where the prefix is the key above:
or-qwen/qwen3.7-plus, nv-openai/gpt-oss-20b, local-llama3.1. Everything after
the prefix is sent verbatim, so slashes in model names are fine. openrouter and
dashscope have built-in base URLs and short prefixes (or, ds); every other key
must supply its own base_url.
This file is fail-closed as a whole. One provider missing
base_urlorapi_keymakes the entire file throw, taking the working providers down with it. Back it up before editing.
extra_body — controlling what the framework does not send
The request body is model / messages / stream / stream_options / tools and
nothing else, so a hosted model's defaults apply untouched — and those defaults can be
expensive. nvidia/nemotron-3.5-lightning-30b-a3b spends 28.0s and 318 output tokens
per tool round on its default reasoning, and 6.1s / 84 tokens with
reasoning_effort: "none".
extra_body is the provider-wide default; model_extra_body overrides it field by
field, keyed by the model name as sent to the provider.
model, messages, stream, stream_options and tools are rejected at load
time, naming the provider and the offending key — not dropped silently. Overriding
stream would hand the SSE reader a single JSON blob; overriding tools would offer
the model tools executeTool cannot run.
Note the terminology clash: the run tool's reasoning_effort argument is a
CLI flag for claude/codex and still does not apply here. What extra_body sends is
the same-named API field, which is a different thing.
max_tool_loops — tool loop budget
Each provider may set "max_tool_loops": 60 in providers.json. It must be an
integer from 1 to 200 (default: 30). This limits both tool-loop iterations and
API completion calls; HTTP retries do not count toward the limit. Reaching the
limit returns finish_reason: "tool_loop_limit" and logs the effective limit
to stderr. Invalid values report the provider name and providers.json path.
The job still ends as completed with exit code 0 and get_result does not
show that stderr line, so check agentOutput.finish_reason before treating the
reply as a finished answer.
retry — surviving a shared endpoint
Free shared endpoints throttle and shed load. NVIDIA's own troubleshooting docs say the hosted Nemotron endpoints may return 429 or 503 under high demand, and advise a short wait plus lower concurrency; before this, any non-200 simply failed the job.
429 and 5xx are retried with exponential backoff and jitter. Every other 4xx is not —
a request the server rejected as malformed is still malformed the second time, and
retrying only burns quota. Defaults are 2 retries and a 1s initial delay;
max_retries: 0 turns it off. A Retry-After header wins over the computed backoff,
capped at 60s. A kill during backoff wakes immediately rather than sleeping it out.
Each retry emits a retry event on stdout — a silent retry makes "slow" and "stuck"
indistinguishable to a caller that only sees the tool result.
Retrying covers establishing the request. Once a 200 arrives and the stream starts, content has already reached the caller, so a mid-stream failure is not retried; replaying it would emit the same answer twice.
Measured on nvidia/nemotron-3-super-120b-a12b, 10 two-round tool loops per row:
| Request pacing | Retry | Success |
|---|---|---|
| back-to-back (~66 rpm) | off | 4/10 |
| 10 rpm | off | 8/10 |
| 15 rpm | off | 9/10 |
| 15 rpm | on | 10/10 |
Slowing down alone never reached 100%; retrying did, and at the faster rate. Even pacing trades every request's latency for a few requests' success, while backoff pays only when the server actually refuses.
replay_reasoning — models that want their own thinking back
Some models require the previous assistant turn to be replayed complete, including
its reasoning. Kimi-K3's model card: "clients must pass back the complete assistant
message, including reasoning_content and tool_calls". DeepSeek V4 goes further —
with tools in play, omitting it returns 400.
"nv": { "replay_reasoning": ["moonshotai/kimi-k3"] }
true covers every model of that provider; an array names them individually.
Off by default, and deliberately not a built-in model list. reasoning_content
is not part of OpenAI's assistant message schema, and "OpenAI-compatible" does not
promise unknown fields are ignored — Azure AI Model Inference defaults extra-parameters
to error. A hardcoded allow-list would also go stale the way every other hardcoded
model list here has.
The replayed value is that turn's reasoning, not the run's accumulated text —
otherwise each round would re-append everything before it. It applies to every
assistant turn, not only the ones carrying tool calls: the final answer is written to
the session file and becomes a prior turn when you continue with the same
session_id.
Measured caveat: Kimi-K3 completed a three-round tool chain correctly without the replay, and the docs do not state what omitting it breaks. This follows the stated contract; it is not a fix for an observed failure.
Knowing what this machine can reach
models returns a directApiProviders block: each configured provider's usable
prefixes (including built-in shorthands), base URL, the models named in
model_extra_body, and a copy-pasteable example.
Without it a tool result cannot answer "what can this machine reach" — the static
direct-api list is four placeholder strings, and configured providers are local
state that lives in neither version control nor any static list.
The block never contains api_key, and never throws: an unreadable providers.json
comes back as a note, because "cannot read it" and "nothing configured" are
different answers.
Limits
- Sessions —
session_idpersists underworkFolder/.tmp/api_sessions. - Images — write
[image:C:/path/to.png]in the prompt (png/jpg/webp/gif). - Plain Q&A — prefix the prompt with
[no-tools]to drop the tool loop. - Per turn — at most 30 API calls and 30 tool-loop iterations.
- Keys — error text is redacted to
[redacted]before it is returned. - Model lists are dynamic; the framework keeps no allow-list.
Migrating from OpenCode: if
providers.jsonis absent but~/.local/share/opencode/auth.jsonexists, it is converted once, automatically.
Auto-update
Precondition: this section applies only to a source clone. The updater requires
.git and package.json in the repo root, so an npm/npx install never updates
itself and doctor reports update.supported: false.
All three MCP entry points (dist/server.js, dist/bin/ai-cli-mcp.js, and
dist/bin/ai-cli.js mcp) serve normally after the transport connects, then check in the
background ~3 seconds later and apply updates in a subprocess; the new version takes
effect on the next start. Nothing blocks startup, and no running server or job is
killed.
AI_CLI_AUTO_UPDATE |
Behavior |
|---|---|
on (default) |
Check in the background, apply automatically |
check |
Report a new version, do not apply |
off |
Never touch the network; still reads existing state |
Also honored: AI_CLI_UPDATE_CHECK_INTERVAL_SEC (default 3600),
AI_CLI_UPDATE_BRANCH, and AI_CLI_STATE_DIR (default ~/.local/state/ai-cli).
⚠️ Treat a push to master as a deployment: npm test must be green before you
push. This is a public repo, and anyone with write access can trigger that.
A source install that tracks master with auto-update on will try to fetch and apply
it on a later check. It does not always land: a dirty tree, a different tracked
branch (AI_CLI_UPDATE_BRANCH), a non-fast-forward or a held lock stops it before
the pull, and a failed install, build or doctor smoke test triggers a rollback
attempt — which can itself fail. So neither "it went everywhere" nor "it went
nowhere" is safe to assume.
Trust model: what on means
AI_CLI_AUTO_UPDATE=on (the default) means trusting every push to origin:
- Anyone who can push to
origin— or anyone who has taken over the repo owner's GitHub account or token — can get this machine to run their code on its next check, with no action from you. - "Takes effect on the next start" refers to the MCP server switching versions. The new
code already runs during the background update: when package files change,
npm installruns the lifecycle scripts of the dependencies and of this repo (such asprepare), and the build anddoctorsmoke test that follow run the new code too. - This server is powerful to begin with: a
runwithoutcapabilitiesstarts each agent with its vendor's permission bypass (--dangerously-skip-permissionsfor claude and agy,--dangerously-bypass-approvals-and-sandboxfor codex,--always-approvefor Grok), using your local CLI logins.
So:
- Use
ononly on machines where you trust whoever can write toorigin, such as your own machines tracking your own repo. - Otherwise —
originpoints at someone else's repo, the machine is shared, or you are not sure who has write access — usecheck: it only reports a new version, and you review the changes before applying them yourself. - On the maintainer side: turn on two-factor authentication for the GitHub account, give
write access only to the people who need it, and protect the
masterbranch.
npm/npx installs are unaffected; they never update themselves.
Architecture
src/
├─ agents/ one file per AI — this is the extension point
│ ├─ types.ts AgentDefinition, the core contract
│ ├─ registry.ts central registry
│ └─ claude.ts · codex.ts · grok.ts · antigravity.ts · direct-api.ts
├─ core/ the framework; untouched when adding an agent
│ ├─ command-builder.ts model routing and command assembly
│ ├─ process-service.ts MCP job management
│ ├─ file-process-service.ts file-backed job management (CLI)
│ ├─ job-store.ts · job-runner.ts shared durable store and detached runner
│ ├─ pty-runner.ts ConPTY, for CLIs that need a real TTY
│ ├─ circuit-breaker.ts start-rate and duplicate-prompt breaker
│ ├─ updater.ts background check, subprocess apply, rollback
│ └─ user-config.ts · binary-resolver.ts · peek.ts · doctor.ts
├─ models/ model catalog, aliases, provenance and disk cache
├─ plugins/ quota lookup bridge
└─ app/ mcp.ts (MCP server) · cli.ts (command line)
The split is the point: agents/ is data about each CLI, core/ is the machinery.
A new backend never requires editing the machinery.
Claude, Codex, Grok and Windows Antigravity (ConPTY) jobs run under a detached runner and outlive their MCP server or
CLI launcher. A restarted MCP server recovers only jobs dispatched by the same
principal process, verified by PID plus OS creation time; recovered results include
recovered: true. Recovery observes existing work and never reruns or retries it.
A recorded exit determines completion; a live verified runner stays running; if
both runner and worker are gone without an exit record, the job becomes lost
and its output remains available. The public PID identifies the runner.
POSIX Antigravity and direct-api remain unrecoverable across MCP
restarts and cannot be adopted. Windows ConPTY workers are held by the detached runner;
PTY stdout combines both streams and strips ANSI, while stderr holds runner errors.
direct-api starts no subprocess at all: on the CLI it runs in-process and blocks until the request
finishes, while the MCP server still returns a PID immediately.
The principal is the first ancestor outside the package launcher chain. Command-line
inspection skips npx-cli.js, npm-cli.js exec/x, and the cmd.exe or POSIX sh
wrappers invoking npx/npm exec. It retains a Node process running Claude Code itself.
This supports both direct Node registration and the npx registration shown above.
Unavailable server/principal identity is reported on stderr and retried on later checks.
Command lines are used for identification only and are never saved in job metadata.
Watching jobs across sessions
Open another terminal using the same state directory:
ai-cli jobs # One table across MCP sessions and CLI jobs
ai-cli jobs --watch # Refresh every 2 seconds; Ctrl+C exits
ai-cli jobs --json # JSON array with metadata and timing
ai-cli jobs --running # Only running jobs; combines with watch/json
ai-cli jobs --watch --json # One compact JSON array per refresh (NDJSON)
ai-cli adopt # Read-only JSON candidates for MCP session adoption
The table shows status (spinner / ✓ / ✗ / ? for lost), agent, resolved model and
reasoning effort, a 40-character task summary, elapsed m:ss, the last short event,
and the dispatching process's parent name plus the ai-cli PID. Narrow terminals
truncate columns without wrapping. Parent names can be shells or Node launchers;
if the OS cannot provide a name, the table shows unknown.
Claude/Codex/Grok and Windows agy (ConPTY) use AI_CLI_STATE_DIR/jobs/<UUID>/ (default
~/.local/state/ai-cli/jobs/). meta.json records the agent, model, effort,
40-character task summary, work folder, session and principal/server/runner/worker
identities. It contains no full prompt. The runner writes metadata and exit.json
atomically once each; the exit record includes code, signal, end time, timeout and
kill flags. For lost jobs, the writer records the first confirmed loss in
lost.json so a long-silent job's output still gets 30 minutes of retention.
Worker stdout/stderr go directly to open stdout.log/stderr.log file descriptors.
On Windows, a short-lived launcher starts the runner and exits before the job is
dispatched. The returned PID remains the runner PID. This keeps durable jobs alive
when Claude Code terminates the MCP server's entire process tree on shutdown.
POSIX keeps its existing detached runner; POSIX agy and direct-api remain unrecoverable.
A temporary stdin file carries the prompt independently of the server
and is removed on completion. Logs can contain prompts or model response excerpts.
bootstrap.json contains only startup metadata and the runner PID, so a failed meta
write does not make the job invisible. Runner identity lookup retries three times with
250/500 ms backoff; failure records a failed exit, removes stdin, and starts no worker.
A job still missing meta after 30 seconds is reported as lost. If meta cannot be saved
after spawning, the runner stops its newly spawned worker and attempts an error exit.
Grok's prompt file moves into this job directory and follows job retention; unclaimed
staging files have exit/timer cleanup and are swept by GC after six hours.
Readers retain byte offsets, parser progress and a 4 KiB tail per stream. They read
only appended bytes; verbose results read at most 8 MiB per stream on demand and return
stdoutTruncated/stderrTruncated byte counts when capped. Oversized parsed replies
also carry agentOutputTruncated. Read the disk logs for larger output. ai-cli run,
ps, result, wait and jobs use this same store, so durable jobs need no second
monitoring snapshot. CLI run waits up to 15 seconds for the metadata handshake;
timeout still returns PID/jobId, a warning and exit 0. Track that job; do not dispatch again.
jobs is read-only and also works with AI_CLI_WORKER=1.
tkflyc-ai-cli MCP Fragen
Wie kann ich das zu Claude Code hinzufügen?
Du kannst es mit dem Befehl hinzufügen: claude mcp add ai-cli -s user -- npx -y @tkflyc/ai-cli-mcp.
Kann ich jede OpenAI-kompatible API nutzen?
Ja, der direct-api Pfad ermöglicht es, jeden OpenAI-kompatiblen /chat/completions Endpoint wie OpenRouter, DeepSeek oder lokales Ollama als Tool zu nutzen.
Werden lokale Modelle unterstützt?
Ja, du kannst lokale Provider wie Ollama konfigurieren, indem du eine Base URL in deiner Provider-Config angibst.