modelcontextprotocol / modelcontextprotocol/servers
[windows-mcp] Scheduled task auto-start fails (0xC0000005) when uvx installed via WinGet symlink; InteractiveToken logon trigger cannot resolve symlink before shell initialization
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 90.5k
- Forks
- 11.7k
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 5
Description
Environment
- OS: Windows 11 (domain-joined, service account
manifold.svc) - Claude Desktop: latest (2026)
- windows-mcp version: installed via WinGet (
astral-sh.uv) - Deployment pattern: MCP server running as Windows Scheduled Task (logon trigger,
InteractiveToken)
Description
When an MCP server is installed via WinGet and launched from a Windows Scheduled Task, the server crashes on auto-start with exit code 0xC0000005 (access violation). The root cause is that WinGet installs binaries as symbolic links under AppData\Local\Microsoft\WinGet\Links\, and Windows Scheduled Tasks with InteractiveToken logon type cannot follow these symlinks before the user shell is fully initialized.
The server works correctly when started manually (Start-ScheduledTask) or launched directly by Claude Desktop — only the at-logon scheduled task trigger fails.
Symptoms
- Scheduled task fires at logon (
Event ID 119— task launched due to user logon) - Task exits immediately with
LastTaskResult: 3221225477(0xC0000005) - Port never becomes available
- Claude Desktop shows the connector as registered but tools never load in new sessions
Root Cause
WinGet installs uvx.EXE as a zero-byte symbolic link:
C:\Users\<user>\AppData\Local\Microsoft\WinGet\Links\uvx.EXE
→ C:\Users\<user>\AppData\Local\Microsoft\WinGet\Packages\astral-sh.uv_Microsoft.Winget.Source_8wekyb3d8bbwe\uvx.exe
The start-server.cmd generated by windows-mcp install points to the symlink path. When Task Scheduler fires the InteractiveToken logon trigger, the user's shell environment is not yet fully initialized, and symlink resolution fails — producing an access violation in the spawned process.
Workaround
Replace the symlink path in start-server.cmd with the real executable path under WinGet\Packages\:
@echo off
setlocal
:: Guard: exit cleanly if another instance is already running on port 8000
netstat -ano | findstr "127.0.0.1:8000" >nul 2>&1
if %ERRORLEVEL% EQU 0 (
echo windows-mcp already running on port 8000, exiting. >> "%USERPROFILE%\.windows-mcp\server.log"
exit /b 0
)
:: Use real path, not WinGet symlink - symlinks fail in scheduled task InteractiveToken context
"C:\Users\<user>\AppData\Local\Microsoft\WinGet\Packages\astral-sh.uv_Microsoft.Winget.Source_8wekyb3d8bbwe\uvx.exe" windows-mcp serve --transport streamable-http --host 127.0.0.1 --port 8000 1>>"%USERPROFILE%\.windows-mcp\server.log" 2>>"%USERPROFILE%\.windows-mcp\server.error.log"
The port guard is also necessary because Claude Desktop may launch its own windows-mcp Extension process on the same port before the scheduled task fires — without the guard, both processes race for port 8000 and the task crashes.
Suggested Fix
windows-mcp install (or the equivalent setup command) should:
- Resolve the real executable path at install time (e.g., via
(Get-Item $symlinkPath).Target) and write the resolved path intostart-server.cmdrather than the symlink path. - Include a port-availability guard in the generated
start-server.cmdto handle the case where Claude Desktop's built-in Extension already owns the port.
Additional Notes
- The issue is reproducible on domain-joined Windows 11 with service accounts where logon sessions may not fully initialize the shell environment before scheduled task triggers fire.
- Task Scheduler Event ID
201with result0xC0000005is the diagnostic signal — not a permissions issue, not a battery/power policy issue. - The same pattern likely affects any MCP server installed via WinGet and launched from a scheduled task.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with windows-mcp install or the equivalent setup command and inspect how it generates start-server.cmd. Verify how the WinGet executable path is written and how scheduled-task startup handles an already-used port. Done means the generated script uses the resolved executable path, avoids a port race, and starts successfully from the logon trigger.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- powershell, shell, typescript
- Domain
- operating-systems, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100