koboldcpp/common
Xuan-Son Nguyen 20455a4ad3
server: support MCP stdio (#26062)
* move server_pipe to common

* init impl

* vendor: update subprocess.h

* add server_mcp_stdio

* stderr drain

* server_mcp_transport

* server_mcp_stdio is now framing-only, no json

* internal/mcp-stdio: integration + tests + fixes (#26075)

* server-mcp: harden transport and wire up the tool integration

Builds on the transport/manager architecture (server_mcp_transport + server_pipe)
with the hardening and integration the draft did not yet have.

Hardening:
* Reader and stderr pumps are polled (running-aware) instead of blocking on a read
  that only ends at EOF. subprocess_terminate() SIGKILLs only the direct child, so a
  grandchild the MCP server spawned that inherited the pipe would otherwise keep the
  write end open and hang teardown (both warmup shutdown at startup and process
  shutdown). The writer is likewise non-blocking + polled.
* Windows: resolve the command through PATHEXT so "npx" (npm ships npx.cmd, never
  npx.exe) spawns, matching POSIX's PATH search; and enumerate the parent environment
  as UTF-8 (GetEnvironmentStringsW) instead of the active code page.
* server_pipe gains an opt-in max_size (default unbounded, so the router's streaming
  use is unchanged); the MCP reply queue uses it so a server that streams unsolicited
  notifications between requests cannot grow it without bound.

Integration:
* --mcp-servers-config / --mcp-servers-json flags; enabling MCP restricts default CORS
  to localhost, same as --tools.
* MCP tools are exposed through /tools (and chat-completions) as <server>_<tool>,
  skipping names that collide with a built-in or another MCP tool.
* Manager lifecycle wired into llama_server(): warmup at start, shutdown() from the
  signal handler before the HTTP server drains, blocking teardown in clean_up().
* SIGPIPE ignored so a child dying mid-write yields EPIPE rather than killing us.

Assisted-By: Claude Opus 4.8 <noreply@anthropic.com>

* server-mcp: add MCP test suite with grandchild deadlock regression test

21 tests over the /tools endpoint: tool discovery/invocation, timeouts, crash
recovery and respawn cooldown, warmup partial failure, malformed and batched
notification+response output, tool-definition shape, and prompt shutdown during a
slow call.

The last test spawns an MCP server that leaves a grandchild inheriting its
stdout/stderr and asserts the server both starts and stops promptly. Verified it
fails (5s SIGKILL fallback on a deadlocked reader-join) when the pump is made to
ignore the running flag, and passes with the polled reader.

Assisted-By: Claude Opus 4.8 <noreply@anthropic.com>

* clean up

* clean up 2

* even stricter life cycle

* nits

* nits 2

---------

Co-authored-by: Xuan Son Nguyen <son@huggingface.co>

* fix some edge cases

* fix last_error data race

* fix response schema + docs

* server: fix MCP zombie leak and timeout-induced transport teardown

join_pumps() never reaped the child, leaking one zombie per spawn:
call subprocess_join() before subprocess_destroy().

A per-call timeout permanently closed from_server and got a healthy
transport evicted: add close_on_stop to server_pipe::read() and pass
false from send_rpc(), where should_stop is a per-request deadline
and a late reply is already skipped on id mismatch.

Also drop the unreachable disconnect cancellation in
server_mcp_tool::invoke(): support_stream is false, st is always null.

(cherry picked from commit e6de1ec043174fd0570b1e60d47f06c7c19d620d)

Assisted-by: Claude Opus 4.8

* server: make MCP test fixtures JSON-RPC 2.0 compliant

Add the missing notification guard to mcp_malformed_server.py and
mcp_burst_server.py (the latter treated id 0 as a notification and
replied to unknown ones; its notification table is now unused).

Return -32602 instead of -32601 for unknown tools: tools/call is a
valid method, the tool name is the invalid parameter.

Also fix the test module docstring: tools are named <server>_<tool>.

(cherry picked from commit 74a08e8c311dabf3b49d06cc6d754b0097ae7a38)

Assisted-by: Claude Opus 4.8

---------

Co-authored-by: Piotr Wilkin (ilintar) <piotr.wilkin@syndatis.com>
Co-authored-by: Pascal <admin@serveurperso.com>
2026-07-26 01:08:49 +02:00
..
jinja minor: fix reasoning preserve var for DS4 [no ci] (#25999) 2026-07-22 14:32:54 +02:00
arg.cpp server: support MCP stdio (#26062) 2026-07-26 01:08:49 +02:00
arg.h arg: fix handling --spec-draft-hf and --hf-repo-v (#25043) 2026-06-26 14:36:03 +02:00
base64.hpp
build-info.cpp.in libs : rename libcommon -> libllama-common (#21936) 2026-04-17 11:11:46 +03:00
build-info.h libs : rename libcommon -> libllama-common (#21936) 2026-04-17 11:11:46 +03:00
chat-auto-parser-generator.cpp Add support for Laguna XS.2 & M.1 (#25165) 2026-07-22 09:54:08 +08:00
chat-auto-parser-helpers.cpp server: fix checkpoints creation (#22929) 2026-05-25 08:56:18 +03:00
chat-auto-parser-helpers.h chat : avoid including json in chat.h (#21306) 2026-04-03 09:07:59 +03:00
chat-auto-parser.h Add support for Laguna XS.2 & M.1 (#25165) 2026-07-22 09:54:08 +08:00
chat-diff-analyzer.cpp Add support for Laguna XS.2 & M.1 (#25165) 2026-07-22 09:54:08 +08:00
chat-peg-parser.cpp chat : fix LFM2 tool-call parsing double-escaping (#24667) 2026-06-15 22:10:09 +02:00
chat-peg-parser.h chat: harden peg-native tool call parsing (#24329) 2026-06-15 15:37:04 +02:00
chat.cpp common : add support for multiple end sequences in the reasoning budget sampler (#25544) 2026-07-25 11:58:09 +02:00
chat.h common : add support for multiple end sequences in the reasoning budget sampler (#25544) 2026-07-25 11:58:09 +02:00
CMakeLists.txt common : add support for multiple end sequences in the reasoning budget sampler (#25544) 2026-07-25 11:58:09 +02:00
common.cpp args: refactor mlock/mmap/directio into load-mode (#20834) 2026-07-23 20:32:56 +08:00
common.h server: support MCP stdio (#26062) 2026-07-26 01:08:49 +02:00
console.cpp cli: fix stripping of \n in multiline input (#21485) 2026-04-06 20:54:06 +02:00
console.h cli : add command and file auto-completion (#19985) 2026-03-05 10:47:28 +01:00
debug.cpp common: fix missing exports in llama-common (#22340) 2026-04-27 08:06:39 +03:00
debug.h common: fix missing exports in llama-common (#22340) 2026-04-27 08:06:39 +03:00
download.cpp common : auto-download dflash- and eagle3- HF sidecars (#25811) 2026-07-17 12:15:30 +03:00
download.h common : auto-download dflash- and eagle3- HF sidecars (#25811) 2026-07-17 12:15:30 +03:00
fit.cpp args: refactor mlock/mmap/directio into load-mode (#20834) 2026-07-23 20:32:56 +08:00
fit.h fit : wrap llama_device_memory_data (#24522) 2026-06-13 08:09:52 +03:00
hf-cache.cpp server: (router) add model management API (#23976) 2026-06-17 18:04:58 +02:00
hf-cache.h server: (router) add model management API (#23976) 2026-06-17 18:04:58 +02:00
http.h cli : move to HTTP-based implementation (#24948) 2026-07-08 14:52:43 +02:00
imatrix-loader.cpp Move duplicated imatrix code into single common imatrix-loader.cpp (#22445) 2026-06-04 17:45:40 +02:00
imatrix-loader.h Move duplicated imatrix code into single common imatrix-loader.cpp (#22445) 2026-06-04 17:45:40 +02:00
json-schema-to-grammar.cpp common/json-schema-to-grammar : align spacing rules with parsers (#24835) 2026-06-20 17:43:04 -05:00
json-schema-to-grammar.h common : add nemotron 3 parsing (#18077) 2025-12-16 04:05:23 -06:00
llguidance.cpp sampling : add support for backend sampling (#17004) 2026-01-04 22:22:16 +02:00
log.cpp common: update logging to enforce max_capacity and optimize queue resizing (#24490) 2026-06-17 09:19:11 +03:00
log.h logs : reduce (#23021) 2026-05-14 13:05:52 +03:00
ngram-cache.cpp spec : add self‑speculative decoding (no draft model required) + refactor (#18471) 2026-01-28 19:42:42 +02:00
ngram-cache.h spec : add self‑speculative decoding (no draft model required) + refactor (#18471) 2026-01-28 19:42:42 +02:00
ngram-map.cpp speculative : fix out-of-bounds read in ngram-map on prompt shrink (#23936) 2026-07-07 10:25:04 +03:00
ngram-map.h fix: correct misspellings in code comments (#21217) 2026-03-31 13:50:51 +02:00
ngram-mod.cpp ngram-mod : Add missing include (#23857) 2026-05-29 09:21:37 +03:00
ngram-mod.h ngram-mod : fix build [no ci] (#19216) 2026-01-30 21:27:27 +02:00
peg-parser.cpp common : add support for multiple end sequences in the reasoning budget sampler (#25544) 2026-07-25 11:58:09 +02:00
peg-parser.h common/peg : implement ac parser for stricter grammar generation (#24869) 2026-06-21 16:20:58 -05:00
preset.cpp common : skip empty implicit default preset (#25643) 2026-07-25 21:15:27 +02:00
preset.h server: (router) rework -hf preset repo (#24739) 2026-06-18 12:45:23 +02:00
reasoning-budget.cpp common : add support for multiple end sequences in the reasoning budget sampler (#25544) 2026-07-25 11:58:09 +02:00
reasoning-budget.h common : add support for multiple end sequences in the reasoning budget sampler (#25544) 2026-07-25 11:58:09 +02:00
sampling.cpp common : add support for multiple end sequences in the reasoning budget sampler (#25544) 2026-07-25 11:58:09 +02:00
sampling.h common : relax sampler name matching (#23744) 2026-06-07 22:48:11 +02:00
speculative.cpp Fix crash with draft-simple (#25720) 2026-07-15 19:51:34 +05:30
speculative.h spec : fix naming, spacing (#25410) 2026-07-07 18:52:30 +03:00
trie.cpp common : add support for multiple end sequences in the reasoning budget sampler (#25544) 2026-07-25 11:58:09 +02:00
trie.h common : add support for multiple end sequences in the reasoning budget sampler (#25544) 2026-07-25 11:58:09 +02:00
unicode.cpp common/parser: handle reasoning budget (#20297) 2026-03-11 10:26:12 +01:00
unicode.h common/parser: handle reasoning budget (#20297) 2026-03-11 10:26:12 +01:00