Repository navigation
Run natively on Windows (1.6.0) - #28
Draft
simonether wants to merge 4 commits into
Draft
simonether wants to merge 4 commits into
simonether wants to merge 4 commits into
Conversation
simonether
force-pushed
the
windows-support
branch
3 times, most recently
from
October 4, 2026 00:29
8ba0831 to
e85eab2
Compare
On Windows `uvx kwork-mcp` failed at import: the state directory, token store and write ledger relied on fcntl, POSIX modes and uids. Platform code now lives in private_fs, with the Win32 calls in windows.py (ctypes, no new dependencies). Windows creates state directories with an owner-only protected DACL, accepts an existing one only if its owner and DACL, inheritable entries included, admit no one but the user, SYSTEM and Administrators, and outside the profile requires that no one else can rename or re-permission the directories above it, as POSIX rejects shared-writable ancestors. It rejects junctions and ambiguous path syntax, checks token and lock files through their handles and the ledger before each connection, seals tokens with DPAPI bound to the account (a record it cannot open asks for a new login), locks with msvcrt and replaces the token with a write-through rename. State stays in ~/.local/state/kwork-mcp under the profile, not in AppData, which packaged (MSIX) clients see virtualized. POSIX behavior and the token format are unchanged. login warns when run elevated, points non-console runs to PowerShell, prints cmd/PowerShell quoting, the Cursor config path and the Edit Config hint for Claude Desktop, and both entry points write UTF-8 to redirected output. CI type-checks the Windows branches and runs the suite and the wheel smoke test on windows-2025.
simonether
force-pushed
the
windows-support
branch
from
October 4, 2026 00:32
e85eab2 to
fa4f91e
Compare
Claude Desktop's Edit Config only reveals claude_desktop_config.json, so connecting it meant editing JSON by hand, worst of all on Windows. After the account is bound, login now finds Claude Desktop (macOS, Windows including the Microsoft Store build with its own AppData copy, community Linux builds) and Cursor, asks, and adds the server entry with the absolute uvx path. Other servers and settings stay as they are, the previous file is kept as .bak, a config that is not plain JSON is never touched, and another server under the same name is replaced only after a separate question. The manual block is printed only for clients that were not connected.
On Windows the first login could not replace the Microsoft Store Claude Desktop config, while the same write succeeded a moment later: something held the file briefly. When the rename is refused, the config is now rewritten in place after the backup, and a failure names its error class and Windows error code instead of a bare 'could not write'.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On Windows
uvx kwork-mcpfailed at import: the state directory, token store and write ledger relied onfcntl, POSIX modes and uids. This adds native Windows support without WSL. macOS and Linux behave as before.All platform code goes through the new
private_fsmodule, with the Win32 calls inwindows.py(ctypes, no new dependencies):CreateDirectoryWwith an owner-only protected DACL (current user and SYSTEM), so a directory never exists with its parent's permissions. An existing directory passes only if its owner is the user, SYSTEM or Administrators and its DACL, inheritable entries included, lets no one else in. OWNER RIGHTS counts as the owner, sinceos.mkdir(path, 0o700)grants it. Outside the profile, no one else may rename or re-permission the directories above the state directory, the counterpart of the POSIX check on shared-writable ancestors. A junction or symlink as the state directory, UNC and device paths, alternate data streams and reserved names are rejected.auth_expired, and a new login replaces it. On POSIX the record stays plain JSON under 0600, so existing stores need no migration.msvcrt.locking. The token is replaced byMoveFileExWwith write-through, since Windows has no directory fsync. Renames and unlinks wait up to a second when an antivirus or the indexer holds a fresh file.~/.local/state/kwork-mcpunder the profile (%USERPROFILE%), not in AppData: packaged (MSIX) clients such as Claude Desktop see a per-app copy of AppData, so the server they start and the terminal would split the ledger and locks.loginwarns when run elevated (that may be another Windows account), points runs outside a console (Git Bash's mintty) to PowerShell, and prints cmd/PowerShell quoting, the Cursor config path and the Edit Config hint for Claude Desktop. Both entry points write UTF-8 to redirected stdout and stderr: in a pipe the cp1252 default crashed--helpon the Russian text.Two independent reviews (Win32 calls against the Microsoft docs; POSIX regressions, tests and docs) found no POSIX regressions; their findings are fixed here. CI gets
mypy --platform win32in the quality job and a Windows job (Python 3.12 and 3.14 on windows-2025) that runs the suite and the wheel smoke test. Coverage stays gated on Linux, where the Windows branches andwindows.pyare excluded. Tests of POSIX-only behavior (modes, umask, symlink walks, directory fsync) are skipped on Windows;tests/test_windows_support.pycovers the Windows side with real ACL, junction, DPAPI and lock checks.README, site and docs describe the Windows setup. Version 1.6.0.
Not checked yet: an interactive
kwork-mcp loginand a real client on a Windows machine, which CI cannot do without a terminal. To try the branch before release: