Scripthold
by zoster81
README.md
# Scripthold — Secure MCP Server for Local Workspaces
<!-- mcp-name: io.github.zoster81/scripthold -->
[](https://github.com/zoster81/scripthold/actions/workflows/test.yml?query=branch%3Amain)
[](https://github.com/zoster81/scripthold/actions/workflows/codeql.yml?query=branch%3Amain)
[](https://scorecard.dev/viewer/?uri=github.com/zoster81/scripthold)
[](https://github.com/zoster81/scripthold/releases/latest)
[](https://github.com/zoster81/scripthold/releases)
[](go.mod)
[](LICENSE)
[](https://registry.modelcontextprotocol.io/?search=io.github.zoster81%2Fscripthold)
[](https://myagenthub.cn/p/io.github.zoster81/scripthold)
[](https://glama.ai/mcp/servers/zoster81/scripthold)
**Code from the web. Work locally. Recover safely.**
Scripthold is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that gives web, desktop, and CLI agents controlled access to explicitly authorized local workspaces. It safely handles legacy text encodings, deterministic file changes, source navigation, backups, and optional durable local execution over stdio or authenticated Streamable HTTP.
AI clients see `Настройки` — not `????` or `Íàñòðîéêè`.
**Start here:** [Quick start](#quick-start) · [Find a tool](TOOLS.md#find-the-right-tool) · [All documentation](docs/README.md) · [Security policy](SECURITY.md).
## What Scripthold provides
Scripthold 4.x provides 36 tools and 3 guided prompts; see [GitHub Releases](https://github.com/zoster81/scripthold/releases/latest) for the latest published version. Clients upgrading from 3.x should follow the [4.0 migration guide](docs/MIGRATION_4.0.md) for the unified confirmation tool. In 4.0.1, the `source_symbols outline` response defaults to a compact tree; pass `presentation: "detailed"` to retain the earlier `files` and `symbols` fields.
- **168 registered text encodings** with content-based detection, UTF-32 LE/BE support, and conservative ambiguity handling.
- **100 active Source Intelligence providers** for bounded declaration navigation, structural search, selected project relations, and verified context assembly.
- **Secure workspace boundaries** with canonical-root containment, Windows reparse/junction handling, deterministic traversal, and missing-path validation.
- **Approval-bound mutations** using preview/apply capabilities, exact fingerprints, conflict checks, staged writes, and truthful partial-state reporting.
- **Optional persistent backups** with history, compare, audit, restore, explicit garbage collection, pinning, and exact-ID deletion.
- **Durable asynchronous tasks** with idempotency, persistent state, bounded logs, recovery, locks, and cancellation.
- **Reliable long-running read-only calls** through optional deferred-operation storage and bounded retained-result retrieval.
- **Authenticated Streamable HTTP** with loopback defaults, bearer authentication, Host/Origin validation, resource limits, and explicit TLS/proxy requirements for non-loopback exposure.
Scripthold originated from the [original `mcp-file-tools` project](https://github.com/dimitar-grigorov/mcp-file-tools), created by **Dimitar Grigorov**, and retains its GPL-3.0 lineage. See [Project Direction](docs/PROJECT_DIRECTION.md).
## Quick start
Choose a published binary or build from source, then configure your MCP client to grant access only to the directories you intend to share. HTTP and container deployments have additional setup below.
### Use a published release
Download the asset for your platform from the [latest release](https://github.com/zoster81/scripthold/releases/latest) and verify it against `checksums.txt`. Releases also attach a signed Sigstore build-provenance bundle for the normal GoReleaser assets.
### Build from source
```bash
git clone https://github.com/zoster81/scripthold.git
cd scripthold
go test ./...
go build -o scripthold ./cmd/scripthold
```
The module path is `github.com/zoster81/scripthold`.
### Local stdio client
Pass each authorized directory as a startup argument:
```json
{
"mcpServers": {
"scripthold": {
"type": "stdio",
"command": "C:\\Tools\\scripthold_windows_amd64.exe",
"args": ["D:\\Projects"]
}
}
}
```
Startup roots are authoritative. A roots-capable stdio client may supply dynamic roots only when the process starts without directory arguments.
### Verified self-update
Supported standalone installations can opt in to self-update. Stop other Scripthold processes using the same binary before running `scripthold update --adopt`. Adoption prepares local state without downloading or replacing the executable.
After adoption, run `scripthold update` to verify and dispatch an available release. Use `scripthold update status` to confirm completion; only run `scripthold update recover` when status offers recovery. These actions have different safety and verification requirements.
See the [Verified Self-update Guide](docs/SELF_UPDATE.md) for supported installations, exact commands, failure handling, and recovery rules.
### Streamable HTTP
HTTP requires exactly one bearer-token source. A minimal loopback PowerShell launch is:
```powershell
$tokenPath = Join-Path $env:TEMP "scripthold.token"
$bytes = New-Object byte[] 32
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
try { $rng.GetBytes($bytes) } finally { $rng.Dispose() }
[System.IO.File]::WriteAllText($tokenPath, [Convert]::ToBase64String($bytes), [System.Text.UTF8Encoding]::new($false))
$env:MCP_HTTP_TOKEN_FILE = $tokenPath
$env:MCP_HTTP_ADDR = "127.0.0.1:8765"
.\scripthold_windows_amd64.exe --transport=streamable-http D:\Projects
```
The MCP endpoint is `http://127.0.0.1:8765/mcp`; `/healthz` and `/readyz` expose liveness/readiness. Send the token as `Authorization: Bearer <token>` on every MCP request.
Do not expose HTTP beyond loopback without reading [HTTP Security](docs/HTTP_SECURITY.md). Non-loopback use requires explicit opt-in and TLS or a trusted proxy boundary.
### OpenAI Secure MCP Tunnel
Sanitized PowerShell examples are available under [`examples/`](examples/):
- [`start-local-stdio.ps1`](examples/start-local-stdio.ps1)
- [`start-local-http.ps1`](examples/start-local-http.ps1)
- [`start-openai-tunnel-stdio-plus-local-http.ps1`](examples/start-openai-tunnel-stdio-plus-local-http.ps1)
- [`start-openai-tunnel-http-plus-local-stdio.ps1`](examples/start-openai-tunnel-http-plus-local-stdio.ps1)
Copy an example outside the checkout before replacing placeholders. Never commit Runtime API keys, Tunnel IDs, bearer tokens, or private state paths.
### Container
```bash
docker build --build-arg VERSION=dev -t scripthold:dev .
docker run --rm -i \
--read-only \
--cap-drop=ALL \
--security-opt=no-new-privileges \
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
--mount type=bind,source=/absolute/project,target=/data \
scripthold:dev --transport=stdio /data
```
The image runs as unprivileged UID/GID `10001`.
## Tool groups
[`TOOLS.md`](TOOLS.md) is the detailed public reference for schemas, parameters, examples, limits, and error behavior. The table below describes the 4.x catalog (36 tools). Clients upgrading from 3.3.6 must migrate the eight former apply commands to `confirm_verified_operation`.
| Area | Main tools |
|---|---|
| Text/files | [`read_text_file`](TOOLS.md#read_text_file), [`read_multiple_files`](TOOLS.md#read_multiple_files), [`write_whole_file`](TOOLS.md#write_whole_file), [`edit_file`](TOOLS.md#edit_file), [`grep_text_files`](TOOLS.md#grep_text_files) |
| Confirmation | [`confirm_verified_operation`](TOOLS.md#confirm_verified_operation) — one-shot approval of any prepared operation |
| Multi-file changes | [`patch_package`](TOOLS.md#patch_package), [`filesystem_package`](TOOLS.md#filesystem_package) |
| Directory/state | [`list_directory`](TOOLS.md#list_directory), [`tree`](TOOLS.md#tree), [`search_files`](TOOLS.md#search_files), [`get_file_info`](TOOLS.md#get_file_info), [`fingerprint_paths`](TOOLS.md#fingerprint_paths), [`verify_state`](TOOLS.md#verify_state) |
| Encoding | [`detect_encoding`](TOOLS.md#detect_encoding), [`convert_encoding`](TOOLS.md#convert_encoding), [`detect_line_endings`](TOOLS.md#detect_line_endings), [`change_line_endings`](TOOLS.md#change_line_endings), [`manage_bom`](TOOLS.md#manage_bom), [`list_encodings`](TOOLS.md#list_encodings) |
| Backups | [`backup_store`](TOOLS.md#backup_store), [`backup_delete`](TOOLS.md#backup_delete) |
| Source Intelligence | [`source_symbols`](TOOLS.md#source_symbols), [`source_query`](TOOLS.md#source_query) |
| Markdown intelligence | [`markdown_read`](TOOLS.md#markdown_read), [`markdown_workspace`](TOOLS.md#markdown_workspace), [`markdown_create`](TOOLS.md#markdown_create), [`markdown_edit`](TOOLS.md#markdown_edit) |
| Durable work | [`task_run`](TOOLS.md#task_run), [`task_list`](TOOLS.md#task_list), [`task_get`](TOOLS.md#task_get), [`task_logs`](TOOLS.md#task_logs), [`task_cancel`](TOOLS.md#task_cancel), [`deferred_operation`](TOOLS.md#deferred_operation) |
| Service | [`list_allowed_directories`](TOOLS.md#list_allowed_directories), [`check_for_updates`](TOOLS.md#check_for_updates) |
## Source Intelligence
Source Intelligence helps agents navigate source code without running it or requiring an external compiler, parser, or language server. Use `source_symbols` to map project files with `digest` `presentation: "compact"`, browse a tree-structured file outline by default (or request `presentation: "detailed"` for the previous outline JSON structure), and inspect a selected symbol; use `source_query` for structural search, supported project relationships, dependency graphs, and verified context. Use `grep_text_files` when looking for arbitrary text or code behavior that is not represented by structural symbols.
Unsupported or ambiguous relationships are rejected rather than guessed. Markdown files have their own [document tools](TOOLS.md#markdown_read). Check the generated [Language Capabilities](docs/LANGUAGE_CAPABILITIES.md) matrix for available source providers and analysis coverage.
## Markdown documents
Markdown files use dedicated tools rather than Source Intelligence providers. Read a document with `markdown_read`, or inspect links and relationships across files with the read-only `markdown_workspace` tool.
To change a document, prepare a preview with `markdown_edit` (or `markdown_create` for a new file), review the proposed content, and pass its `previewId` to `confirm_verified_operation`. Unsafe, conflicting, or stale changes are rejected instead of being silently rewritten.
For examples and the exact operation forms, see the [Markdown tool reference](TOOLS.md#markdown_read). For Markdown semantics, supported encodings, and the Marksplice integration boundary, see [Markdown Intelligence](docs/MARKDOWN_INTELLIGENCE.md).
## Safety model
- File access is limited to explicitly authorized roots after canonical path validation.
- Symlink, junction, reparse-point, alias, and missing-path escapes fail closed.
- Encoding detection uses bytes and decoded-content evidence, never filenames or extensions.
- Mutations stage and revalidate before commit; initially missing destinations use no-replace semantics.
- Preview/apply workflows bind the approved operation to a one-shot capability so mutation parameters cannot be changed at apply time.
- Multi-file mutations do not claim transactional rollback; failures report committed/unchanged/unknown state where applicable.
- The optional backup store is a separate protected authority outside public roots.
- `task_run` execution is disabled by default. Shell and script execution require explicit authorization; HTTP requires an additional HTTP execution opt-in.
- HTTP is authenticated and loopback-only by default.
Current architectural boundaries are summarized in [Architecture](docs/ARCHITECTURE.md).
## Key configuration
Most installations need only a small subset of environment variables:
| Variable | Purpose | Default |
|---|---|---|
| `MCP_TRANSPORT` | `stdio` or `streamable-http` | `stdio` |
| `MCP_DEFAULT_ENCODING` | Encoding for new text files | `utf-8` |
| `MCP_HTTP_ADDR` | HTTP listen address | `127.0.0.1:8765` |
| `MCP_HTTP_TOKEN_FILE` / `MCP_HTTP_TOKEN` | Mutually exclusive bearer-token sources | unset |
| `MCP_HTTP_ALLOW_NON_LOOPBACK` | Permit non-loopback binding when other security requirements are met | disabled |
| `MCP_BACKUP_STORE_DIR` | Enable the persistent backup store | unset |
| `MCP_BACKUP_DEFAULT_POLICY` | Default persistent backup policy for eligible approval-bound mutations | `disabled` |
| `MCP_TASK_STORE_DIR` | Enable durable task persistence | unset |
| `MCP_DEFERRED_STORE_DIR` | Enable durable ownership for eligible long-running read-only calls | unset |
| `MCP_ENABLE_RUN_SCRIPT` | Allow `task_run kind=script` | disabled |
| `MCP_ENABLE_SHELL` | Allow `task_run kind=shell` | disabled |
| `MCP_ENABLE_EXECUTION` | Allow both task kinds | disabled |
| `MCP_HTTP_ENABLE_EXECUTION` | Additional HTTP execution gate | disabled |
Detailed limits and subsystem-specific options are documented where they are used: [TOOLS.md](TOOLS.md), [Durable Tasks](docs/DURABLE_TASKS.md), and [HTTP Security](docs/HTTP_SECURITY.md).
## Documentation
Use the [Documentation Guide](docs/README.md) to find instructions by task, whether you are configuring a client, choosing a tool, securing a deployment, or contributing to the project.
- **Using the server:** [Tool Reference](TOOLS.md), [HTTP Security](docs/HTTP_SECURITY.md), and [Durable Tasks](docs/DURABLE_TASKS.md).
- **Understanding and changing the project:** [Architecture](docs/ARCHITECTURE.md), [Contributing](CONTRIBUTING.md), and [Roadmap](docs/ROADMAP.md).
- **Release history:** [Changelog](CHANGELOG.md), with version-specific steps in the [migration guides](docs/README.md#use-scripthold).
## Development
The required Go version is declared by `go.mod`.
```bash
go mod verify
go test ./...
golangci-lint run ./...
go build -o scripthold ./cmd/scripthold
```
See [CONTRIBUTING.md](CONTRIBUTING.md) before proposing changes.
## License
GPL-3.0 — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityActive
ResponsivenessNo issues