Platter
io.github.hadriangateway由 GitHub 账号 hadriangateway 发布v2.0.3更新于 Oct 25, 2026
MCP server exposing Read, Write, Edit, Bash, Glob, Grep, and JS tools over stdio.
概览
本地 MCP 服务器,让助手在用户自己的机器上读写和编辑文件、执行 shell 命令、按模式查找文件、搜索内容并运行 JavaScript。
- 可以做什么
- 读取、创建和覆盖文件,支持分页、图片元数据识别和自动创建父目录;查找替换式编辑返回统一 diff,可全部替换或模糊匹配。按 glob 模式列出文件,或用 ripgrep 做正则内容搜索,支持文件过滤和上下文行。执行带可选超时的 shell 命令,或在持久 Node.js 上下文中运行 JavaScript/TypeScript,状态在会话内跨调用保留,并可从 unpkg.com 加载包。
- 适用场景
- 适合让助手直接处理本地项目:查看和修改源码、搜索代码库、运行构建或 git 命令、试验小段脚本。适用于桌面机器上的编程和文件管理任务。
- 运行要求
- 以本地进程运行(Linux 或 macOS 的发布二进制、Docker 镜像,或用 Bun 从源码构建)。默认 stdio,也可用 HTTP 模式,支持 OAuth、bearer 或 JWKS 认证及 TLS。grep 工具需要预先安装 ripgrep(rg)。stdio 使用未声明任何环境变量或凭据。
安装
在 SourceWeft 中
- 打开 控制台中的 Platter,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
platter
Your computer, served on a platter.
MCP server that exposes Read, Write, Edit, Bash, Glob, Grep, and JS tools over Stdio and StreamableHTTP transports. Built with Bun, compiles to standalone executables.
Designed to be used by browser-based (or any MCP-compatible) agents, like Hadrian, to control a computer.
Tools
Quick start
From a release binary
Download the latest binary for your platform from Releases, or grab it with curl:
Docker
See Docker below for mounting paths, networking, installing extra software, and building custom images.
From source
Usage
Restrictions
You can limit which tools are registered, which filesystem paths file tools can access, and which commands the bash tool can execute.
Tool selection
Only register specific tools. Unregistered tools are completely hidden from MCP clients:
Path restrictions
Restrict file-accessing tools (read, write, edit, glob, grep) to one or more directory trees. Paths are resolved to absolute form and symlinks are resolved via realpath to prevent escaping:
Command restrictions
Only allow bash commands whose entire command string matches at least one regex pattern:
Patterns are anchored: --allow-command "git( .*)?" compiles to ^(?:git( .*)?)$, so git status matches but rm -rf / && git status does not.
Combined example
Active restrictions are logged to stderr at startup.
Authentication
Controlled by --auth <mode>:
OAuth 2.1 (--auth oauth)
MCP clients that support RFC 9728 (Protected Resource Metadata) can discover platter's OAuth endpoints automatically and authenticate without manual token copying.
The flow:
- Client discovers
/.well-known/oauth-authorization-serverand/.well-known/oauth-protected-resource/mcp - Client registers via
POST /register(RFC 7591 dynamic client registration) - Client initiates Authorization Code + PKCE flow via
/authorize - A confirmation code is displayed out-of-band (printed to stderr, or shown as a desktop notification in tray mode)
- User sees a consent page, enters the confirmation code, selects which tools to grant, and approves or denies the request
- Client exchanges the authorization code for tokens at
/token - Subsequent requests use
Authorization: Bearer <access_token>
The confirmation code proves that the person approving the request has access to the platter process — a remote attacker who can reach the consent page cannot approve without it. Codes are single-use and expire after 5 minutes, with a maximum of 5 attempts.
Access tokens expire after 1 hour and can be refreshed. Client registrations are persisted to ~/.config/platter/clients.json. A static bearer token is also accepted as a fallback for clients that don't support OAuth.
Bearer token (--auth bearer)
A random bearer token is generated at startup and printed to stderr (or stored in the system keyring in tray mode). Every request must include Authorization: Bearer <token>. You can provide your own:
No authentication (--auth none)
Disable authentication entirely (e.g. behind a reverse proxy that handles auth):
External JWKS / OIDC (--auth jwks)
In jwks mode platter acts as a pure resource server: it does not mint its own tokens. Instead it verifies JWT access tokens issued by an external OAuth/OIDC authorization server (Auth0, Keycloak, Okta, Microsoft Entra) — validating the signature against the issuer's JWKS, plus the iss, aud, and exp claims. This lets you put platter behind your existing IdP without a reverse proxy.
Audience validation (strongly recommended). Set --oauth-audience to the API identifier configured in your IdP. If you omit it, platter accepts any valid token from the issuer — including tokens minted for a different resource server (a confused-deputy risk). platter prints a warning at startup when audience validation is disabled.
Discovery. With --oauth-issuer, platter fetches the issuer's /.well-known/openid-configuration (falling back to /.well-known/oauth-authorization-server) at startup to find the jwks_uri and re-advertise the authorization server to RFC 9728-capable MCP clients (at /.well-known/oauth-protected-resource/mcp). Pass --jwks-url to skip discovery, or if the IdP isn't reachable at startup. If discovery fails but --jwks-url is set, token verification still works — only the RFC 9728 auto-advertisement is skipped.
Authorization (what a token can do). By default a verified token gets admin-level access, bounded only by the operator's CLI restrictions (--tools, --allow-path, --allow-command, --sandbox) — the IdP controls who gets in, the CLI flags control what they can do. Pass --jwks-scope-grants to additionally honor tools:<name> scopes in the token (e.g. tools:read tools:bash), which further narrow the granted tools (they can only narrow, never widen the operator's ceiling). The scope claim and Entra-style scp claim are both supported. In this mode access is fail closed: a token carrying no tools:* scope is granted no tools at all, so a token must explicitly request the tools it needs.
No static fallback. Unlike oauth mode, jwks mode accepts only externally-issued JWTs — --auth-token is rejected.
Note:
MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URLis unrelated to this mode. It only concerns platter serving its own issuer over http in--auth oauthmode. An externalhttpsissuer needs no such flag. If you point--auth jwksat a plain-httpissuer (e.g. a localhost Keycloak), platter warns and skips RFC 9728 metadata advertisement, but token verification still works.
TLS (HTTPS)
To serve over HTTPS, provide a PEM-encoded certificate and private key:
Both --tls-cert and --tls-key are required together. When provided, the server listens over HTTPS instead of plain HTTP.
To generate a self-signed certificate for development or trusted internal use:
Stdio mode
For use with Claude Desktop, Cursor, and other MCP clients that spawn a subprocess:
HTTP mode (StreamableHTTP)
For browser-based agents and remote connections:
The server exposes a single endpoint at /mcp that handles:
POST /mcp- JSON-RPC messages (initialize, tool calls)GET /mcp- SSE notification streamDELETE /mcp- session teardown
CORS is enabled for all origins by default (reflects the request Origin). To restrict to a specific origin:
Sessions are managed via the Mcp-Session-Id header per the StreamableHTTP spec.
The server validates the Host header to prevent DNS rebinding attacks. When --cors-origin is set, the Origin header is also validated server-side (not just via CORS response headers).
Tray mode (Linux)
Run platter as a persistent background service with a system tray icon:
This implies --transport=http and adds:
- System tray icon via DBus (StatusNotifierItem protocol), compatible with KDE, GNOME (with AppIndicator extension), and other desktop environments.
- Persistent configuration in
~/.config/platter/config.json— auth token, enabled tools, port, host, and working directory survive restarts. - Dynamic tool toggling — enable or disable individual tools at runtime from the tray menu. Changes are persisted and take effect immediately.
- Auth token management — copy the server URL or auth token to clipboard, or regenerate the token. Tokens are stored in the system keyring when available, falling back to the config file.
- Server controls — start, stop, and restart the HTTP server from the tray menu.
Linux installer
The linux/install.sh script performs a user-level install (no sudo required):
This installs:
~/.local/bin/platter— the binary~/.local/share/applications/platter.desktop— desktop launcher entry~/.local/share/icons/hicolor/scalable/apps/platter.svg— application icon~/.config/systemd/user/platter.service— systemd user unit for autostart
Security
Network (HTTP mode)
- TLS (HTTPS) - optional transport encryption via
--tls-certand--tls-key. Uses Node.jshttpsmodule with PEM-encoded certificate and key files. - OAuth 2.1 + PKCE (
--auth oauth, default) - MCP clients authenticate via Authorization Code flow with PKCE (RFC 7636). Supports dynamic client registration (RFC 7591) and token revocation (RFC 7009). - External JWKS / OIDC (
--auth jwks) - resource-server mode: platter verifies JWT access tokens from an external issuer (Auth0, Keycloak, Okta, Entra) against the issuer's JWKS, validating signature,iss,aud, andexp. Asymmetric algorithms only (alg: noneand HMAC are rejected). See the External JWKS / OIDC section under Authentication for configuration. - Out-of-band consent confirmation - the OAuth consent page requires a confirmation code that is only displayed to the platter operator (via stderr or desktop notification). This prevents CSRF and cross-origin attacks from auto-approving authorization requests. The consent page is also protected with
X-Frame-Options: DENY,Sec-Fetch-Sitevalidation, andOriginheader checking. - Bearer token authentication - a static bearer token (RFC 6750) is available as a fallback in
oauthmode and as the sole method inbearermode. A random 256-bit token is generated at startup unless you provide--auth-tokenor set--auth none. - Host header validation - prevents DNS rebinding attacks. Localhost binds accept only
127.0.0.1,localhost, and::1; remote binds accept only the specified--host. - Origin validation - when
--cors-originis set to a specific origin, requests with a mismatchedOriginheader are actively rejected with 403 (not just filtered by CORS response headers).
Restrictions (best-effort)
--tools, --allow-path, and --allow-command are defense-in-depth controls. They raise the bar significantly but are not a sandbox. The limitations below should be understood before relying on them in a threat model.
What they do well
- Tool selection is enforced at registration time. Disabled tools are never exposed via the MCP protocol. There is no way for a client to invoke or discover them.
- Path validation resolves symlinks via
realpath()on both the target and each allowed path before comparison, preventing traversal via../or symlinked directories. For write targets that don't exist yet, the nearest existing ancestor is resolved instead. - Command validation anchors regex patterns to match the full command string, preventing trivial bypasses like appending
&& malicious-command.
Known limitations and bypasses
- Bash is inherently unrestricted. When the bash tool is enabled, a sufficiently creative command can bypass
--allow-pathentirely (e.g.cat /etc/passwd). If you set--allow-pathwithout also setting--allow-commandor removing bash from--tools, a warning is printed at startup. For strong file-access control, either disable bash (--tools read,write,edit,glob,grep) or pair--allow-pathwith a tight--allow-commandallowlist. - The
jstool is not a security sandbox. It runs code in a Node.jsvmcontext, which Node's own documentation explicitly states is not a security mechanism — untrusted code can escape the context via known techniques. Even without an escape, the runtime exposesfetch(arbitrary network access, including private/loopback addresses),Buffer, and aload()helper that downloads and executes arbitrary code fromunpkg.comor any other URL. None of--allow-path,--allow-command,--sandbox, or--sandbox-allow-urlapply to thejstool — these flags only affect the file and bash tools. If thejstool is enabled, treat the server as having roughly the same blast radius as unrestricted bash. To disable it:--tools read,write,edit,bash,glob,grep. For strong isolation, run platter inside a container or VM. - Command regex operates on the raw string. It does not parse shell syntax. Patterns like
--allow-command "git( .*)?"blockrm && git status(because the full string doesn't match), but a determined attacker could construct commands that the regex matches yet that execute unintended code, for example if an allowed pattern is too broad. Write patterns as narrowly as possible. - Symlink TOCTOU. Path validation resolves symlinks at check time. If a symlink target is changed between the check and the actual file operation, the validation can be bypassed. This is a fundamental limitation of userspace path checking.
- Glob/grep search scope.
--allow-pathvalidates the search directory for glob and grep, but results within that directory tree may include symlinks pointing outside it. The content of those symlink targets could be returned in grep output or listed by glob. - No process-level sandboxing. All restrictions are enforced in application code within the platter process. They do not use OS-level mechanisms (seccomp, namespaces, pledge, etc.). A vulnerability in platter itself, Bun, or a dependency could bypass all restrictions.
For stronger isolation, use the just-bash sandbox, a Docker container, or both.
Sandbox mode (just-bash)
Opt into just-bash, a TypeScript reimplementation of bash with a virtual filesystem, for sandboxed command execution. No native processes are spawned; the shell runs entirely in the Bun runtime.
Filesystem modes
Network access
Network access is disabled by default. Use --sandbox-allow-url (repeatable) to allow access to specific URL prefixes. Private/loopback IPs are always denied.
Interaction with other restrictions
--allow-path: Inreadwriteandoverlaymodes, each allowed path is mounted into the sandbox. Inmemorymode,--allow-pathis ignored.--allow-command: Command regex validation still applies before the sandbox executes the command.--sandboxsuppresses the bash +--allow-pathwarning, since the sandbox enforces filesystem boundaries.
Limitations
- Not full bash. just-bash is a TypeScript reimplementation; some edge cases may behave differently from GNU bash.
- No native binaries. Commands like
git,node,docker,rg,pythonare not available. Only bash builtins and just-bash's built-in command set work. - Beta software. just-bash is under active development. Test your workflows before relying on it in production.
Container isolation (Docker)
Running platter inside a Docker container provides OS-level isolation via Linux namespaces and cgroups. The container boundary limits what the bash tool can access. Even unrestricted commands can only reach the filesystems and network that the container exposes.
What the container enforces
- Filesystem boundary. Only explicitly mounted paths (
-v) are visible. Even with bash enabled, commands cannot read or write host paths that aren't mounted. - Network boundary.
--network nonecompletely disables networking. Without it, the container has outbound access but no access to host-only services unless--network hostis used. - Process isolation. Processes inside the container cannot see or signal host processes.
- Resource limits. Docker's
--memory,--cpus, and--pids-limitflags can cap resource usage to prevent denial of service.
Containers vs VMs
Containers share the host kernel; isolation is enforced by kernel features (namespaces, cgroups, seccomp). A kernel vulnerability or a misconfigured container (e.g. --privileged) can break the boundary. VMs run a separate kernel on virtualised hardware, so a guest compromise does not directly expose the host. If your threat model includes untrusted code that may attempt kernel exploits, run platter inside a VM (or a VM-backed container runtime like Kata Containers or Firecracker). For most use cases, like limiting blast radius from an AI agent, a properly configured container (non-root, capabilities dropped, --network none) is sufficient.
Combining sandbox and container
The just-bash sandbox and Docker container address different layers. Used together, they provide defense in depth:
For the highest security posture, also run the container as a non-root user (--user), drop all capabilities (--cap-drop ALL), and set the filesystem read-only (--read-only) with a tmpdir for any needed writes:
See Docker for full usage instructions including mounting paths, networking, and building custom images.
Docker
The Docker image is based on Debian Bookworm (slim) and includes ripgrep. Multi-arch images (linux/amd64, linux/arm64) are published to GitHub Container Registry on every tagged release.
Running in stdio mode
Pipe JSON-RPC messages via stdin/stdout:
Running in HTTP mode
Bind to 0.0.0.0 inside the container so the port is reachable from the host:
Mounting paths
Mount host directories into the container and use --cwd or --allow-path to give platter access:
Networking
By default containers have full outbound network access. You can restrict this with Docker's network options:
Installing additional software at runtime
The image uses Debian, so you can install packages with apt-get at runtime. This is useful for quick experiments but adds startup latency. For production use, build a custom image instead (see below).
Or interactively:
Building a custom image
Layer additional tools on top of the platter image for a ready-to-use environment:
Build and run:
Building the image locally
Build
License
MIT
来源:README.md,提交 0610019
工具
0版本历史
1- v2.0.3最新Sep 16, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分