ContextBridge MCP server
Commit 13 Nov 2026Gateway self-hosted yang memberikan akses aman dan terkendali bagi AI assistant ke file, command, dan proses lokal maupun remote melalui kebijakan tertentu.
Juga dikenal sebagai Deep-Sixed/ContextBridge
- Stars
- 1
- Tools
- —
- Unduhan, 30 hari
- —
- Versi terbaru
- —
- Commit terakhir
- 13 Nov 2026
- Lisensi
- MIT
Apa itu ContextBridge MCP?
ContextBridge adalah MCP server. Gateway self-hosted yang memberikan akses aman dan terkendali bagi AI assistant ke file, command, dan proses lokal maupun remote melalui kebijakan tertentu.
Ringkasan dibuat dari README proyek
Tentang ContextBridge MCP server
ContextBridge memberikan AI assistant akses yang aman dan terkendali melalui kebijakan ke file, command, dan proses lokal maupun remote Anda melalui gateway self-hosted. Layanan ini beroperasi tanpa hosted relay, menggunakan agent dan transport sendiri untuk menjaga privasi. Developer dapat memilih di antara dua route berbeda: Filesystem route untuk mengelola direktori spesifik, dan Computer route untuk akses sistem yang lebih luas termasuk proses, perangkat, dan dokumen.
Untuk menggunakan layanan ini, Anda harus mengonfigurasi token autentikasi khusus untuk setiap route, seperti CONTEXTBRIDGE_FS_AUTH_TOKEN dan CONTEXTBRIDGE_COMPUTER_TOKEN. Filesystem route memungkinkan kontrol granular terhadap root direktori, menawarkan tool seperti read_file, edit_block, dan kemampuan background search. Computer route juga dapat melayani remote MCP client seperti Claude atau ChatGPT melalui endpoint yang dilindungi OAuth. Setup ini memastikan bahwa AI agent hanya berinteraksi dengan perangkat dan izin spesifik yang Anda setujui secara eksplisit.
Apa yang bisa Anda lakukan dengannya
- 1Mengelola file proyek lokalAI assistant dapat membaca, mengedit, atau memindahkan file di dalam direktori spesifik yang telah Anda berikan izin.
- 2Mengontrol hardware dan sistem remoteDeveloper dapat memberikan akses kepada AI agent ke file, command, dan proses pada perangkat remote yang terdaftar.
Ditulis berdasarkan README proyek. Setiap use case diperiksa terhadap kutipan dari README tersebut.
Konfigurasi
CONTEXTBRIDGE_COMPUTER_TOKENCONTEXTBRIDGE_FS_AUTH_TOKEN
| Nama | Deskripsi | Tipe |
|---|---|---|
| CONTEXTBRIDGE_COMPUTER_TOKEN | — | |
| CONTEXTBRIDGE_FS_AUTH_TOKEN | — |
Pengecekan otomatis
Berjalan 15 Nov 2026Laporan lengkap →Belum diverifikasi. Sebuah server memerlukan skor 80, tidak ada temuan serius, dan data yang cukup untuk kami periksa. Cara kerja checks · Yang perlu diperbaiki untuk menambah poin
- Source repository terhubung dan dapat dijangkaudeep-sixed/contextbridge is public and reachablegithub.com/deep-sixed/contextbridge ↗Lolos
- Nama paket mencantumkan repositori ini sebagai sumbernyaTidak diperiksa
- Provenance build (atestasi Sigstore)Tidak diperiksa
- Lisensi open source (OSI)MITspdx.org/licenses/MIT.html ↗Lolos
- Ada commit atau release dalam satu tahun terakhirLast commit or release 2026-11-13github.com/deep-sixed/contextbridge ↗Lolos
- OpenSSF ScorecardTidak diperiksa
- Nama package tidak mirip dengan package populerTidak diperiksa
- Tidak ada advisory kritis pada paket atau dependensinyaTidak diperiksa
- Tidak ada instruksi tersembunyi untuk model0 tool descriptions and the README read; no override phrases, credential paths or hidden charactersLolos
- Tools yang bersifat destruktif telah diberi labelTidak diperiksa
- Endpoint remote merespons handshake MCPTidak diperiksa
README
Lihat di GitHubContextBridge
A self-hosted MCP gateway that gives AI assistants authenticated, policy-controlled access to your own computers. ContextBridge has no runtime dependency on any hosted relay: its own gateway, agents, and transport do the work.
It has two routes, each with its own server, port, and credential:
| Route | Module | Tools | Credential |
|---|---|---|---|
| Filesystem | contextbridge.filesystem.gateway |
file tools inside configured directories (see Filesystem route) | CONTEXTBRIDGE_FS_AUTH_TOKEN |
| Computer | contextbridge.computer |
files, search, documents, commands, sessions, processes, devices; opt-in window and media inventory | CONTEXTBRIDGE_COMPUTER_TOKEN |
Each route accepts only its own token, and each refuses to start if its token matches the other route's, when both are set in its environment.
The computer route can also serve ChatGPT, Claude, and other remote MCP clients through a second, OAuth-protected endpoint. Each client gets only the permissions and devices you approve for it (see Remote MCP clients).
Installation
python3 -m pip install -e '.[test]'
python3 -m pytest # includes acceptance tests that launch the gateways and an agent as real processes
ContextBridge requires Python 3.11+ and FastMCP 3.x (fastmcp>=3,<4). It has no runtime dependency on Node or npx, and the acceptance tests run both gateways in an environment without them.
tests/test_fs.py covers the filesystem operations and path rules, and tests/test_fs_gateway.py pins the filesystem route's MCP contract (tool set, annotations, schemas, reported version, default-deny for every other method) and starts its entrypoint. CI runs the whole suite on Ubuntu and Windows, with Python 3.11 against the oldest supported FastMCP (3.0.0) and Python 3.13 against the newest 3.x release.
Filesystem route
python -m contextbridge.filesystem.gateway (or ./scripts/run-contextbridge-fs.sh) is a separate MCP server on port 8794. It gives agents file access inside the directories listed under filesystem.roots in configs/contextbridge-fs.yaml. The shipped config lists none, so the route refuses to start until you add some.
export CONTEXTBRIDGE_FS_AUTH_TOKEN="<a different strong secret>"
./scripts/run-contextbridge-fs.sh
CONTEXTBRIDGE_FS_AUTH_TOKEN is required, must be at least 32 characters (for example python3 -c "import secrets; print(secrets.token_urlsafe(32))"), and must differ from CONTEXTBRIDGE_COMPUTER_TOKEN when that is set. Set CONTEXTBRIDGE_FS_CONFIG to use another config file.
MCP clients connect over streamable HTTP to http://127.0.0.1:8794/mcp and send Authorization: Bearer <CONTEXTBRIDGE_FS_AUTH_TOKEN>. Every HTTP route requires the token, including GET /, which returns the service name, the MCP path, and the tool names. A request without a valid token gets 401 and is audited as auth.
| Setting | Default | Purpose |
|---|---|---|
serve.host |
127.0.0.1 |
Listen address; keep it on loopback |
serve.port |
required | Listen port (8794 in configs/contextbridge-fs.yaml) |
name |
ContextBridge Files |
Server name reported in serverInfo and by GET / |
CONTEXTBRIDGE_FS_AUDIT_LOG or serve.audit_log |
unset | Audit log file (see Audit below) |
serve.forwarded_allow_ips |
unset | Proxy addresses whose X-Forwarded-For is trusted for the audited peer |
CONTEXTBRIDGE_MCP_TOOL_TIMEOUT_SECONDS |
10 |
Timeout for a tool call |
CONTEXTBRIDGE_MCP_METADATA_TIMEOUT_SECONDS |
5 |
Timeout for initialize and tools/list |
filesystem |
required | Roots and limits (below) |
Where a setting has both an environment variable and a config key, the environment variable wins. An unset, unparsable, or non-positive timeout falls back to the default. Relative paths in the config are resolved against the config file's directory.
Other MCP methods are default-deny: resources/list, resources/templates/list and prompts/list return empty lists, ping is answered, and every other request (for example resources/read, prompts/get, logging/setLevel) is rejected and audited. Error details are masked from clients.
Path rules: every path must be absolute or start with ~ (the server user's home directory). It is resolved with symlinks followed and must land inside a root, so .. and symlinks cannot reach outside. Roots are read-only unless they set writable: true, must exist, and must not overlap. The server's MCP instructions list each root and whether it is writable. Write tools are only advertised when at least one root is writable, and calls to any tool outside the advertised set are denied and audited.
| Tool | Input | Notes |
|---|---|---|
read_file |
path, offset, length |
UTF-8 text by line; a negative offset reads the last lines; length defaults to 1000 |
read_multiple_files |
paths |
Up to 50 files; one file's error does not fail the rest |
list_directory |
path, depth |
depth 1–10, default 2; symlinks are listed, not followed |
get_file_info |
path |
Size, timestamps, permissions, type, whether it is a symlink |
write_file |
path, content, mode |
rewrite (replaces an existing file atomically, keeping its permissions) or append; the parent must exist |
edit_block |
file_path, old_string, new_string, expected_replacements |
Exact text; fails unless the match count equals expected_replacements (default 1) |
create_directory |
path |
Creates missing parents |
move_file |
source, destination |
Moves or renames; refuses a destination that already exists |
delete_file |
path, recursive |
Moves the item to <root>/.contextbridge-trash/; a non-empty directory needs recursive |
start_search |
path, pattern, search_type, file_pattern, ignore_case, literal, include_hidden, context_lines, max_results, timeout_ms |
Starts a recursive search in the background and returns a search_id, its status, and the first 100 results |
get_more_search_results |
search_id, offset, length |
A page of results (up to 500); a negative offset counts from the end |
stop_search |
search_id |
Stops a running search; the results found so far stay available |
list_searches |
none | Recent searches with their status and result counts |
Read tools, including the four search tools, are annotated read-only and are offered even when every root is read-only. write_file, edit_block and delete_file are marked destructive.
Search: search_type is files (the default) or content.
- A
filessearch matches file and directory names. The pattern is a glob if it contains*,?or[, and a substring otherwise. - A
contentsearch matches each line of a text file against a regular expression (Pythonresyntax), or against a plain string withliteral: true. Results have thepath, the 1-basedlinenumber and the line'stext, plusbeforeandafterlists whencontext_lines(0–10) is set. ignore_casedefaults to true.file_patternlimits which files are searched, for example*.pyor*.{ts,tsx}|*.md, and is matched against file names case-insensitively. Withfile_patternset, afilessearch reports only files, not directories.- Hidden entries (names starting with
.) are skipped unlessinclude_hiddenis true.
The search starts at path (a directory, or a single file for a content search) and walks every level below it. Symlinks are reported by a files search but never followed, and the trash is never searched. A content search skips binary files (a NUL byte in the first 8 KiB) and files over max_search_file_bytes, and reports the counts in skipped. Lines longer than 500 characters are cut, and a match on a cut line is marked truncated.
start_search waits up to one second, so a quick search returns complete. A longer one keeps running, and get_more_search_results returns its results so far, with status: "running" and has_more: true until it finishes. The final status is completed, cancelled, timed_out or failed; limit_reached is true when max_results (default 500, at most 5000) or the 8 MiB per-search cap stopped it early.
Each search runs in its own worker process (src/contextbridge/filesystem/search_worker.py, started with python -I), so stop_search and timeout_ms (default 30000, at most 300000) stop it even inside a slow regular expression. On Linux and macOS the worker also sets an alarm a few seconds past its timeout, so it ends even if the server dies first. At most 4 searches run at once. The 10 most recent are kept in memory, and the oldest finished one is dropped to make room, so search ids are not kept across restarts. Searches are shared: every client with the route's token can list, page through and stop them.
Deletion is recoverable: each deleted item is kept under .contextbridge-trash/<trash_id>/, next to a <trash_id>.json file recording its original path. No tool can read, list, change or empty the trash; recover or purge items from the host.
Limits: max_read_bytes and max_write_bytes (1 MiB each by default) cap a response and a write, max_list_entries (1000) caps a listing, and max_search_file_bytes (10 MiB) is the largest file a content search reads. Text must be UTF-8; binary files are refused.
Audit: each MCP request except ping, and each HTTP request rejected by auth, is one JSON line with route: "fs", written to stderr (prefixed [fs audit] ) and, if set, to CONTEXTBRIDGE_FS_AUDIT_LOG (or serve.audit_log). The file is opened without following symlinks, must be a regular file, and is set to mode 0600. Each line has a unique request_id. Denied tools and methods are logged with detail: "policy_denied" and without their arguments; requests rejected by bearer auth are logged as tool: "auth" with missing_token, invalid_token, or forbidden. Client-supplied strings are cut to 200 characters. The peer field is the TCP peer address; X-Forwarded-For is ignored unless serve.forwarded_allow_ips lists the proxy. Paths are logged as the client sent them, with byte counts for reads and writes and the trash location for deletes. Refused paths are logged with detail: "path_denied". Search events include search_id and result counts; patterns are logged only by length and hash.
Known limits: checks run before each operation, so another local process that swaps a symlink in between can still redirect it; only the final component is opened with O_NOFOLLOW. Likewise, a destination created between move_file's check and the rename is replaced. Hard links that already exist inside a root are not detected.
Computer route
The computer route serves files, search, commands, processes, and documents on the gateway's own machine and on enrolled remote devices. Every tool takes a device argument: local (the gateway's own machine, the default) or the name of an enrolled remote device (see Remote devices). list_devices shows what is reachable. A tool is offered only when some device's policy enables it:
| Tool | Enabled on a device when |
|---|---|
list_directory, read_file, get_file_info, search_files, search_code, get_system_info |
always (read-only) |
write_file, edit_block, create_directory, move_file |
filesystem.writable_roots is non-empty |
delete_file |
writable roots, and filesystem.delete is trash (default) or permanent |
list_deleted, restore_deleted |
writable roots, and filesystem.delete: trash |
read_document |
always (read-only) |
write_document, edit_document, write_spreadsheet, edit_pdf |
filesystem.writable_roots is non-empty |
run_command, start_process, read_process_output, interact_with_process, force_terminate, list_sessions |
commands.mode is not disabled |
list_processes |
processes.list: true |
kill_process |
processes.allow_kill: true |
list_windows |
desktop.observe: true (see Desktop and media inventory) |
media_inventory |
media.discover: true |
list_devices |
always |
Running it
The computer route serves HTTP on a loopback address only. It will not start without its own token of at least 32 characters, a loopback serve.host, and a writable serve.audit_log.
export CONTEXTBRIDGE_COMPUTER_TOKEN="$(openssl rand -hex 32)" # keep it in your secret manager
./scripts/run-computer.sh # http://127.0.0.1:8791/mcp
Set CONTEXTBRIDGE_COMPUTER_CONFIG to use another config file.
Local MCP clients connect with the token as a bearer header. For example, in Claude Code:
claude mcp add --transport http contextbridge http://127.0.0.1:8791/mcp \
--header "Authorization: Bearer $CONTEXTBRIDGE_COMPUTER_TOKEN"
There is no unauthenticated mode. Every MCP request is checked against the token.
Authorization
These checks run on every tool call, at the moment it executes:
- Token scope. The bearer token must carry the tool's scope:
computer:read(file reading, search, system info, process listing,list_devices),computer:write(file changes),computer:execute(commands and sessions),computer:process(kill_process),desktop:observe(list_windows), ormedia:discover(media_inventory).auth.scopesin the config sets what the token carries; without it the token carries all six, but the shippedconfigs/computer.yamlgrants only the fourcomputer:*scopes. Tools outside those scopes are hidden from the tool list and refused if called anyway. - Device. A remote (OAuth) client may only use the devices its grant names. The local token reaches every device. The device must exist and be online. Its policy must enable the tool. A remote device must also have been granted the tool's scope when it was paired.
- Policy checks. The device's engine re-validates every path, command, working directory, and limit before acting. For a remote device, that's the agent on that machine, under its own policy.
Policy
- Paths. Every path resolves through symlinks before it is checked, so neither
..nor a symlink can escapefilesystem.roots. Writes are allowed only insidefilesystem.writable_roots. Any path with a component matching adenyglob (.ssh,.env*,*.pem,*.kdbx, and so on) is hidden from listings and searches and refused for reads and writes. The policy file and the audit log can never be written or moved through ContextBridge. - Limits. Reads, writes, search results, and search time all have caps. A
search_coderegular expression is matched in a separate worker process that is killed whenmax_search_secondsruns out, so a slow pattern cannot stall the gateway or an agent. Rewrites are atomic and preserve file mode.edit_blockfails unless the match count is exactly what the caller expected. - Commands.
allowlistmode runs one program per call without a shell. The program must be on the allowlist, and pipes, redirects,;and&&are refused before anything runs.unrestrictedmode runs through a shell:bash -cby default (PowerShell on Windows), or whatevercommands.shellnames (bash,sh,powershell,pwsh,cmd, or an argv list). The working directory must be inside a readable root. Every command has a hard timeout (max_timeout_secondscaps whatever the caller asks for), and a timed-out command is killed along with every process it started. Output is capped in memory, keeping the head and the tail. Variables that look like credentials (*TOKEN*,*SECRET*,*PASSWORD*, …) are removed from the child's environment, and both route tokens (CONTEXTBRIDGE_FS_AUTH_TOKEN,CONTEXTBRIDGE_COMPUTER_TOKEN) are always removed, whateverenv_stripsays, as is the retiredMCP_AUTH_TOKEN. On Linux every ContextBridge server also marks itself non-dumpable at startup, so a command cannot read the tokens back out of the server's own/proc/<pid>/environ(ps eshows exactly that); as a side effect the servers write no core dumps and attaching a debugger to one needs root. - Sessions.
start_processruns long or interactive programs in the background. Concurrent sessions are capped (max_sessions) and each is killed when it reachesmax_session_seconds. - Deletes.
delete_fileworks only inside writable roots. It never deletes a root, a protected or hidden path, or a folder holding anything the file tools may not see (a.sshor.envinside, say). A non-empty folder needsrecursive: trueand is capped atmax_delete_entries(10,000).delete: trash(default): the item moves to.contextbridge-trash/<trash_id>/in its writable root, beside a<trash_id>.jsonrecord of where it came from.list_deletedshows the trash andrestore_deletedputs an item back, but no file tool can read, change, or empty the trash, so a client cannot make its own deletions permanent. Empty it on the host. The layout is the filesystem route's, so a folder both routes serve has one trash.delete: permanent: removes the item outright.delete: disabled: removes the tool.
Documents
read_document reads PDF, Word (.docx), and Excel (.xlsx, .xlsm) files; read_file is for text and points to it.
- PDF: text per page, with
pageslike1-3,7(50 pages per call). - Word: the document as Markdown (headings, lists, and tables) plus a heading outline.
- Excel: sheet names and cell values for a
sheetandcell_range(10,000 cells per call).formulas: trueshows formulas instead of the values Excel last calculated. find: searches inside any of them and returns the pages, blocks, or cells that match.
Writing needs a writable root:
write_document: creates or replaces a.docxor.pdffrom simple Markdown (#headings,-and1.lists,| a | b |tables, paragraphs). PDFs use a Unicode font when the machine has one (DejaVu, Segoe UI, or Arial).edit_document: replaces exact text in a.docx(body, tables, headers, and footers). Likeedit_block, it fails unless the match count is exactly what the caller expected. Formatting is kept when a match sits inside one formatted run; a match spanning runs takes the paragraph's first run's formatting. Text inside hyperlinks and fields is not matched.write_spreadsheet: writes rows of values into a sheet starting atstart_cell, creating the.xlsxor the sheet if needed and keeping everything else. A string starting with=is stored as a formula. New workbooks must be.xlsx; existing.xlsmfiles keep their macros.edit_pdf: deletes, rotates, or inserts pages (from another PDF), in place or intooutput_path.
Documents go through the same path policy as every file tool. Files over max_document_bytes (20 MiB) are not opened. Word and Excel files are checked for zip bombs before parsing, and XML is parsed without entity expansion. The libraries (pypdf, python-docx, openpyxl, reportlab, defusedxml) are dependencies. A device without them doesn't offer the document tools.
Know the boundary. The command allowlist controls which programs run, not what they touch. git diff --no-index can read any file the OS user can, for example. Allowing a program that can run other programs makes allowlist mode equivalent to unrestricted: a shell, an interpreter, or git, whose -c options and aliases run any command, so the example configs leave git out. They also leave out ps: ps e prints the environment of every process the OS user runs, and that is where other programs keep their tokens and API keys (the servers warn at startup if ps is on the allowlist; list_processes shows processes without their environment). The filesystem deny list applies to the file tools, not to commands. For a hard boundary, run the computer route as a dedicated OS user that can only reach what you intend to share.
Desktop and media inventory
Both tools are off by default and only report; neither captures the screen, sends input, records, or plays anything. Each needs the device policy switch and the token scope.
list_windows(desktop.observe: true, scopedesktop:observe) returns up to 200 visible windows, each with anidand atitlecut to 256 characters. Window titles can reveal what you are working on. On Windows it lists visible top-level windows of the interactive desktop. On Linux it needs a graphical session (DISPLAYorWAYLAND_DISPLAY) andwmctrl; without them the call fails.media_inventory(media.discover: true, scopemedia:discover) returns device-count hints, never opening a device: on Linux the number of/dev/video*nodes, on Windows the number of audio input and output devices. Counts it cannot get arenull, and a count is not proof that a device works.
docs/phase-2-desktop-plan.md describes the planned next steps (session discovery, screen capture, input), none of which exist yet.
Pertanyaan tentang ContextBridge MCP
Apa yang bisa dilakukan ContextBridge untuk AI assistant?
ContextBridge menyediakan akses terautentikasi dan terkendali melalui kebijakan ke komputer Anda sendiri, termasuk file, pencarian, dokumen, command, sesi, proses, dan perangkat.
Bisakah saya menggunakan ContextBridge dengan ChatGPT atau Claude?
Ya, computer route dapat melayani remote MCP client seperti ChatGPT dan Claude melalui endpoint kedua yang dilindungi oleh OAuth.
Apakah penghapusan file bersifat permanen pada filesystem route?
Secara default, penghapusan dapat dipulihkan; item akan dipindahkan ke direktori trash tersembunyi, meskipun Anda dapat mengonfigurasinya untuk penghapusan permanen.
Apa persyaratan sistem untuk instalasi?
ContextBridge memerlukan Python 3.11 atau versi yang lebih tinggi dan FastMCP 3.x.