Skip to content
Closed
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
6a58f91
server: add MCP protocol type definitions
ochafik Dec 23, 2025
625437e
server: add subprocess management for MCP servers
ochafik Dec 23, 2025
e29d5c6
server: add WebSocket server implementation
ochafik Dec 23, 2025
ac9a585
server: add MCP bridge for routing WebSocket to subprocesses
ochafik Dec 23, 2025
ca5507e
server: integrate MCP support with --mcp-config option
ochafik Dec 23, 2025
91e92fc
webui: add MCP service and type definitions
ochafik Dec 23, 2025
dc1d2f9
webui: add MCP state management stores
ochafik Dec 23, 2025
78ec1f4
webui: add tool call and result display components
ochafik Dec 23, 2025
7b8e9c2
webui: add MCP server management UI
ochafik Dec 23, 2025
83b49d0
webui: integrate MCP tool calling with chat
ochafik Dec 23, 2025
17efe37
server: add MCP tests
ochafik Dec 23, 2025
e9179dd
server: add MCP documentation and example config
ochafik Dec 23, 2025
ad6ed55
webui: redesign MCP picker to match model selector style
ochafik Dec 23, 2025
70e0f90
webui: only show tool status when calling or complete
ochafik Dec 24, 2025
745fb7b
webui: move model/stats bar below tool blocks
ochafik Dec 24, 2025
19a2a91
fix: address CI failures
ochafik Dec 24, 2025
ad134cd
feat: add cwd attribute to MCP server config
ochafik Dec 24, 2025
462cc65
Update index.html.gz
ochafik Dec 24, 2025
ee9ca7a
webui: add MCP SDK dependency and handle all tool result content types
ochafik Dec 24, 2025
b92f477
chore: update webui build output
ochafik Dec 24, 2025
0257e6b
revert: remove unrelated hf_repo name change from branch
ochafik Dec 24, 2025
08b51dc
server: add --webui-mcp flag and cleanup MCP bridge
ochafik Dec 24, 2025
42558ac
fix: handle Sec-WebSocket-Protocol header in MCP WebSocket handshake
ochafik Dec 24, 2025
fc773f6
update index.html.gz
ochafik Dec 24, 2025
c5efe84
refactor: harden WebSocket server and simplify MCP types
ochafik Dec 24, 2025
6cbaaaf
chore: update webui build output
ochafik Dec 24, 2025
2e25d63
chore: drop /mcp/ws-port endpoint, simplify WS port discovery
ochafik Dec 24, 2025
4c703a2
chore: lower WS connection limit to 10 (env configurable)
ochafik Dec 24, 2025
0a6da98
docs: add subprocess.h evaluation to PR TODOs
ochafik Dec 24, 2025
07a0203
chore: update webui build output
ochafik Dec 24, 2025
cee558f
refactor: replace server-mproc with subprocess.h
ochafik Dec 24, 2025
663dfb1
fix: subprocess security hardening
ochafik Dec 24, 2025
8a5d2e5
update index.html.gz
ochafik Dec 24, 2025
771a80f
update index.html.gz
ochafik Dec 24, 2025
bcc0f97
fix: WebSocket connection leak + reuse existing SHA1/base64 libs
ochafik Dec 24, 2025
4de84d0
fix: MCP WebSocket mutex deadlock + Processing... display
ochafik Dec 24, 2025
cde3ee7
test: fix MCP unit tests and add webui_mcp flag support
ochafik Dec 24, 2025
1cf7588
test: add env var filtering test and use --mcp-config flag
ochafik Dec 24, 2025
ef9a21f
refactor: extract MCP echo server to fixtures file
ochafik Dec 24, 2025
6aacf85
debug: add console logging for MCP tool calls
ochafik Dec 24, 2025
568709a
test: use official MCP SDK in Python tests
ochafik Dec 24, 2025
4a18dc0
style: fix formatting in MCP service and chat store
ochafik Dec 24, 2025
8d82104
fix: increase WebSocket timeout to prevent MCP connection drops
ochafik Dec 24, 2025
1b159bd
refactor: reduce verbose MCP console logging
ochafik Dec 24, 2025
321ebf5
feat: add bearer token authentication to WebSocket server
ochafik Dec 24, 2025
e74ea7d
custom SSE + HTTP POST transport
ngxson Dec 25, 2025
2724d3f
Merge pull request #5 from ngxson/xsn/chafik_webui_mcp_idea
ochafik Dec 25, 2025
5e8ee5c
refactor(mcp): inline MCP bridge, use streaming HTTP proxy
ochafik Dec 25, 2025
d054762
Update index.html.gz
ochafik Dec 25, 2025
1598b35
fix: add missing mutex include for Windows, fix pyright type error
ochafik Dec 25, 2025
75b2a84
fix: remove unused sha1-ws library (WebSocket leftover)
ochafik Dec 25, 2025
386cde9
fix: restore CORS headers (Access-Control-Allow-Credentials, wildcard…
ochafik Dec 25, 2025
cc13d95
fix: remove WebSocket tests (WebSocket support was removed)
ochafik Dec 25, 2025
0b6e088
refactor: unroll header erase loop for clarity
ochafik Dec 25, 2025
ca3dae2
feat: add HTTPS support for MCP proxy
ochafik Dec 25, 2025
69b684c
feat: add fs_get_config_directory() and fs_get_config_file()
ochafik Dec 25, 2025
23d1b00
feat(mcp): restore WebSocket <-> stdio bridge for local MCP servers
ochafik Dec 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion common/arg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,17 @@ static handle_model_result common_params_handle_model(
model.path = common_docker_resolve_model(model.docker_repo);
model.name = model.docker_repo; // set name for consistency
} else if (!model.hf_repo.empty()) {
// use hf_repo as name if not already set
if (model.name.empty()) {
model.name = model.hf_repo;
}
// short-hand to avoid specifying --hf-file -> default it to --model
if (model.hf_file.empty()) {
if (model.path.empty()) {
auto auto_detected = common_get_hf_file(model.hf_repo, bearer_token, offline);
if (auto_detected.repo.empty() || auto_detected.ggufFile.empty()) {
exit(1); // built without CURL, error message already printed
}
model.name = model.hf_repo; // repo name with tag
model.hf_repo = auto_detected.repo; // repo name without tag
model.hf_file = auto_detected.ggufFile;
if (!auto_detected.mmprojFile.empty()) {
Expand Down Expand Up @@ -2697,6 +2700,13 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
params.ssl_file_cert = value;
}
).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_SSL_CERT_FILE"));
add_opt(common_arg(
{"--mcp-config"}, "FNAME",
"path to MCP server configuration JSON file",
[](common_params & params, const std::string & value) {
params.mcp_config = value;
}
).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_MCP_CONFIG"));
add_opt(common_arg(
{"--chat-template-kwargs"}, "STRING",
string_format("sets additional params for the json template parser"),
Expand Down
3 changes: 3 additions & 0 deletions common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,9 @@ struct common_params {

std::map<std::string, std::string> default_template_kwargs;

// MCP config
std::string mcp_config = ""; // NOLINT

// webui configs
bool webui = true;
std::string webui_config_json;
Expand Down
6 changes: 6 additions & 0 deletions tools/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ set(TARGET_SRCS
server-common.h
server-context.cpp
server-context.h
server-ws.cpp
server-ws.h
server-mproc.cpp
server-mproc.h
server-mcp-bridge.cpp
server-mcp-bridge.h
)
set(PUBLIC_ASSETS
index.html.gz
Expand Down
71 changes: 71 additions & 0 deletions tools/server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1679,6 +1679,77 @@ Apart from error types supported by OAI, we also have custom types that are spec
}
```

### MCP (Model Context Protocol) Support

The server supports [MCP](https://modelcontextprotocol.io/) for integrating external tools via WebSocket. MCP enables models to interact with external services like file systems, databases, APIs, and more.

#### MCP Configuration

Create an MCP configuration file (JSON format):

```json
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"],
"env": {}
},
"brave-search": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-brave-search"],
"env": {
"BRAVE_API_KEY": "your-api-key"
}
}
}
}
```

#### MCP Configuration Location

The server looks for MCP configuration in the following order:
1. `--mcp-config` command-line argument
2. `LLAMA_MCP_CONFIG` environment variable
3. `~/.llama.cpp/mcp.json` (Linux/macOS)
4. `%APPDATA%/llama.cpp/mcp.json` (Windows)

#### MCP Usage

```bash
# Use default config location (~/.llama.cpp/mcp.json)
./llama-server -m model.gguf

# Or specify config path
./llama-server -m model.gguf --mcp-config /path/to/mcp.json

# Or use environment variable
LLAMA_MCP_CONFIG=/path/to/mcp.json ./llama-server -m model.gguf
```

#### MCP WebSocket Port

MCP uses WebSocket on HTTP port + 1 (default: 8081 when HTTP is on 8080). The frontend discovers the actual port via the `/mcp/ws-port` endpoint.

#### MCP API Endpoints

| Endpoint | Description |
|----------|-------------|
| `GET /mcp/servers` | List available MCP servers from configuration |
| `GET /mcp/ws-port` | Get the WebSocket port number |
| `WS /mcp?server=<name>` | WebSocket connection (on port+1) |

#### MCP Protocol

The MCP bridge implements JSON-RPC 2.0 over WebSocket. Key methods:
- `initialize` - Establish MCP session
- `tools/list` - List available tools
- `tools/call` - Execute a tool
- `resources/list` - List available resources
- `resources/read` - Read a resource

For more information about MCP, see the [Model Context Protocol documentation](https://modelcontextprotocol.io/).

### Legacy completion web UI

A new chat-based UI has replaced the old completion-based since [this PR](https://github.com/ggml-org/llama.cpp/pull/10175). If you want to use the old completion, start the server with `--path ./tools/server/public_legacy`
Expand Down
45 changes: 45 additions & 0 deletions tools/server/mcp_config.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"_comment": "Example MCP configuration for llama.cpp",
"_comment_windows": "On Windows, place this file in %APPDATA%\\llama.cpp\\mcp.json",
"_comment_macos": "On macOS/Linux, place this file in ~/.llama.cpp/mcp.json",
"_comment_env": "Or set the LLAMA_MCP_CONFIG environment variable to point to this file",
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/allowed/path"
]
},
"brave-search": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-brave-search"
],
"env": {
"BRAVE_API_KEY": "your-api-key-here"
}
},
"github": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-github"
],
"env": {
"GITHUB_TOKEN": "your-github-token-here"
}
},
"_comment_cwd_example": "Example: Run a custom MCP server script from a specific directory",
"my-script": {
"command": "python",
"args": ["server.py"],
"cwd": "/path/to/working/directory",
"env": {
"PYTHONUNBUFFERED": "1"
}
}
}
}
Binary file modified tools/server/public/index.html.gz
Binary file not shown.
6 changes: 5 additions & 1 deletion tools/server/server-http.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,14 @@ bool server_http_context::start() {
return true;
}

void server_http_context::stop() const {
void server_http_context::stop() {
if (pimpl->srv) {
pimpl->srv->stop();
}
// Wait for server thread to finish
if (thread.joinable()) {
thread.join();
}
}

static void set_headers(httplib::Response & res, const std::map<std::string, std::string> & headers) {
Expand Down
2 changes: 1 addition & 1 deletion tools/server/server-http.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ struct server_http_context {

bool init(const common_params & params);
bool start();
void stop() const;
void stop();

// note: the handler should never throw exceptions
using handler_t = std::function<server_http_res_ptr(const server_http_req & req)>;
Expand Down
Loading
Loading