@mokoconsulting/mcp-windows 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +94 -0
- package/.gitmessage +9 -0
- package/.mokogitea/ISSUE_TEMPLATE/adr.md +110 -0
- package/.mokogitea/ISSUE_TEMPLATE/bug_report.md +48 -0
- package/.mokogitea/ISSUE_TEMPLATE/config.yml +18 -0
- package/.mokogitea/ISSUE_TEMPLATE/documentation.md +52 -0
- package/.mokogitea/ISSUE_TEMPLATE/feature_request.md +51 -0
- package/.mokogitea/ISSUE_TEMPLATE/mcp_api_integration.md +48 -0
- package/.mokogitea/ISSUE_TEMPLATE/mcp_connection_issue.md +67 -0
- package/.mokogitea/ISSUE_TEMPLATE/mcp_tool_request.md +49 -0
- package/.mokogitea/ISSUE_TEMPLATE/question.md +82 -0
- package/.mokogitea/ISSUE_TEMPLATE/rfc.md +126 -0
- package/.mokogitea/ISSUE_TEMPLATE/security.md +51 -0
- package/.mokogitea/ISSUE_TEMPLATE/version.md +24 -0
- package/.mokogitea/branch-protection.yml +251 -0
- package/.mokogitea/workflows/auto-assign.yml +76 -0
- package/.mokogitea/workflows/auto-bump.yml +66 -0
- package/.mokogitea/workflows/auto-dev-issue.yml +207 -0
- package/.mokogitea/workflows/auto-release.yml +421 -0
- package/.mokogitea/workflows/branch-cleanup.yml +48 -0
- package/.mokogitea/workflows/cascade-dev.yml +10 -0
- package/.mokogitea/workflows/changelog-validation.yml +101 -0
- package/.mokogitea/workflows/ci-generic.yml +191 -0
- package/.mokogitea/workflows/cleanup.yml +87 -0
- package/.mokogitea/workflows/codeql-analysis.yml +115 -0
- package/.mokogitea/workflows/copilot-agent.yml +44 -0
- package/.mokogitea/workflows/deploy-manual.yml +126 -0
- package/.mokogitea/workflows/enterprise-firewall-setup.yml +758 -0
- package/.mokogitea/workflows/gitleaks.yml +92 -0
- package/.mokogitea/workflows/issue-branch.yml +73 -0
- package/.mokogitea/workflows/mcp-auto-release.yml +278 -0
- package/.mokogitea/workflows/mcp-build-test.yml +65 -0
- package/.mokogitea/workflows/mcp-sdk-check.yml +109 -0
- package/.mokogitea/workflows/mcp-tool-inventory.yml +61 -0
- package/.mokogitea/workflows/notify.yml +70 -0
- package/.mokogitea/workflows/npm-publish.yml +113 -0
- package/.mokogitea/workflows/pr-check.yml +534 -0
- package/.mokogitea/workflows/pre-release.yml +252 -0
- package/.mokogitea/workflows/rc-revert.yml +66 -0
- package/.mokogitea/workflows/repo-health.yml +712 -0
- package/.mokogitea/workflows/repository-cleanup.yml +525 -0
- package/.mokogitea/workflows/security-audit.yml +82 -0
- package/.mokogitea/workflows/standards-compliance.yml +2614 -0
- package/.mokogitea/workflows/sync-version-on-merge.yml +133 -0
- package/.mokogitea/workflows/update-server.yml +312 -0
- package/.mokogitea/workflows/workflow-sync-trigger.yml +73 -0
- package/CHANGELOG.md +130 -0
- package/CLAUDE.md +49 -0
- package/CONTRIBUTING.md +161 -0
- package/ISSUES.md +601 -0
- package/Makefile +70 -0
- package/README.md +80 -0
- package/automation/ci-issue-reporter.sh +237 -0
- package/config.example.json +18 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +111 -0
- package/dist/shell.d.ts +50 -0
- package/dist/shell.js +209 -0
- package/dist/tools/apps.d.ts +3 -0
- package/dist/tools/apps.js +63 -0
- package/dist/tools/audio.d.ts +3 -0
- package/dist/tools/audio.js +142 -0
- package/dist/tools/audio_apps.d.ts +3 -0
- package/dist/tools/audio_apps.js +86 -0
- package/dist/tools/automation.d.ts +3 -0
- package/dist/tools/automation.js +261 -0
- package/dist/tools/bluetooth.d.ts +3 -0
- package/dist/tools/bluetooth.js +96 -0
- package/dist/tools/clipboard.d.ts +3 -0
- package/dist/tools/clipboard.js +118 -0
- package/dist/tools/config.d.ts +3 -0
- package/dist/tools/config.js +85 -0
- package/dist/tools/dialog.d.ts +3 -0
- package/dist/tools/dialog.js +72 -0
- package/dist/tools/display.d.ts +3 -0
- package/dist/tools/display.js +256 -0
- package/dist/tools/drives.d.ts +3 -0
- package/dist/tools/drives.js +98 -0
- package/dist/tools/environment.d.ts +3 -0
- package/dist/tools/environment.js +129 -0
- package/dist/tools/execute.d.ts +3 -0
- package/dist/tools/execute.js +28 -0
- package/dist/tools/filesystem.d.ts +3 -0
- package/dist/tools/filesystem.js +230 -0
- package/dist/tools/firewall.d.ts +3 -0
- package/dist/tools/firewall.js +108 -0
- package/dist/tools/hosts.d.ts +3 -0
- package/dist/tools/hosts.js +119 -0
- package/dist/tools/maintenance.d.ts +3 -0
- package/dist/tools/maintenance.js +236 -0
- package/dist/tools/netstat.d.ts +3 -0
- package/dist/tools/netstat.js +56 -0
- package/dist/tools/network.d.ts +3 -0
- package/dist/tools/network.js +70 -0
- package/dist/tools/notification.d.ts +3 -0
- package/dist/tools/notification.js +41 -0
- package/dist/tools/power.d.ts +3 -0
- package/dist/tools/power.js +104 -0
- package/dist/tools/printer.d.ts +3 -0
- package/dist/tools/printer.js +97 -0
- package/dist/tools/process.d.ts +3 -0
- package/dist/tools/process.js +54 -0
- package/dist/tools/process_kill.d.ts +3 -0
- package/dist/tools/process_kill.js +48 -0
- package/dist/tools/recycle_bin.d.ts +3 -0
- package/dist/tools/recycle_bin.js +108 -0
- package/dist/tools/registry.d.ts +3 -0
- package/dist/tools/registry.js +136 -0
- package/dist/tools/scheduler.d.ts +3 -0
- package/dist/tools/scheduler.js +116 -0
- package/dist/tools/service.d.ts +3 -0
- package/dist/tools/service.js +79 -0
- package/dist/tools/startup.d.ts +3 -0
- package/dist/tools/startup.js +159 -0
- package/dist/tools/storage.d.ts +3 -0
- package/dist/tools/storage.js +129 -0
- package/dist/tools/system.d.ts +3 -0
- package/dist/tools/system.js +84 -0
- package/dist/tools/system_mgmt.d.ts +3 -0
- package/dist/tools/system_mgmt.js +174 -0
- package/dist/tools/terminal.d.ts +3 -0
- package/dist/tools/terminal.js +80 -0
- package/dist/tools/theme.d.ts +3 -0
- package/dist/tools/theme.js +165 -0
- package/dist/tools/usb.d.ts +3 -0
- package/dist/tools/usb.js +52 -0
- package/dist/tools/virtual_desktop.d.ts +3 -0
- package/dist/tools/virtual_desktop.js +112 -0
- package/dist/tools/wifi.d.ts +3 -0
- package/dist/tools/wifi.js +136 -0
- package/dist/tools/window.d.ts +3 -0
- package/dist/tools/window.js +189 -0
- package/dist/tools/winget.d.ts +3 -0
- package/dist/tools/winget.js +79 -0
- package/dist/tools/wsl.d.ts +3 -0
- package/dist/tools/wsl.js +99 -0
- package/docs/API.md +63 -0
- package/docs/ARCHITECTURE.md +73 -0
- package/docs/INSTALLATION.md +102 -0
- package/docs/index.md +12 -0
- package/package.json +35 -0
- package/scripts/setup.mjs +123 -0
- package/src/index.ts +125 -0
- package/src/shell.ts +253 -0
- package/src/tools/apps.ts +76 -0
- package/src/tools/audio.ts +161 -0
- package/src/tools/audio_apps.ts +98 -0
- package/src/tools/automation.ts +297 -0
- package/src/tools/bluetooth.ts +114 -0
- package/src/tools/clipboard.ts +138 -0
- package/src/tools/config.ts +105 -0
- package/src/tools/dialog.ts +87 -0
- package/src/tools/display.ts +285 -0
- package/src/tools/drives.ts +124 -0
- package/src/tools/environment.ts +146 -0
- package/src/tools/execute.ts +35 -0
- package/src/tools/filesystem.ts +273 -0
- package/src/tools/firewall.ts +125 -0
- package/src/tools/hosts.ts +135 -0
- package/src/tools/maintenance.ts +299 -0
- package/src/tools/netstat.ts +72 -0
- package/src/tools/network.ts +84 -0
- package/src/tools/notification.ts +50 -0
- package/src/tools/power.ts +123 -0
- package/src/tools/printer.ts +114 -0
- package/src/tools/process.ts +80 -0
- package/src/tools/process_kill.ts +57 -0
- package/src/tools/recycle_bin.ts +126 -0
- package/src/tools/registry.ts +165 -0
- package/src/tools/scheduler.ts +140 -0
- package/src/tools/service.ts +102 -0
- package/src/tools/startup.ts +180 -0
- package/src/tools/storage.ts +141 -0
- package/src/tools/system.ts +99 -0
- package/src/tools/system_mgmt.ts +190 -0
- package/src/tools/terminal.ts +117 -0
- package/src/tools/theme.ts +205 -0
- package/src/tools/usb.ts +65 -0
- package/src/tools/virtual_desktop.ts +122 -0
- package/src/tools/wifi.ts +157 -0
- package/src/tools/window.ts +211 -0
- package/src/tools/winget.ts +100 -0
- package/src/tools/wsl.ts +112 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
2
|
+
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
+
*
|
|
4
|
+
* Tools: windows_window_list (#14), windows_window_control (#15)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { runPowerShell } from '../shell.js';
|
|
8
|
+
const WIN32_TYPES = `
|
|
9
|
+
Add-Type @'
|
|
10
|
+
using System;
|
|
11
|
+
using System.Text;
|
|
12
|
+
using System.Collections.Generic;
|
|
13
|
+
using System.Runtime.InteropServices;
|
|
14
|
+
|
|
15
|
+
public class WindowManager {
|
|
16
|
+
[DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
|
17
|
+
[DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd);
|
|
18
|
+
[DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
|
|
19
|
+
[DllImport("user32.dll")] public static extern int GetWindowTextLength(IntPtr hWnd);
|
|
20
|
+
[DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
|
|
21
|
+
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|
22
|
+
[DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
|
23
|
+
[DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd);
|
|
24
|
+
[DllImport("user32.dll")] public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
|
|
25
|
+
[DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
|
|
26
|
+
[DllImport("user32.dll")] public static extern bool IsIconic(IntPtr hWnd);
|
|
27
|
+
[DllImport("user32.dll")] public static extern bool IsZoomed(IntPtr hWnd);
|
|
28
|
+
[DllImport("user32.dll")] public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
|
|
29
|
+
|
|
30
|
+
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
|
31
|
+
|
|
32
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
33
|
+
public struct RECT { public int Left, Top, Right, Bottom; }
|
|
34
|
+
|
|
35
|
+
public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
|
|
36
|
+
public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
|
|
37
|
+
public const uint SWP_NOMOVE = 0x0002;
|
|
38
|
+
public const uint SWP_NOSIZE = 0x0001;
|
|
39
|
+
public const uint WM_CLOSE = 0x0010;
|
|
40
|
+
}
|
|
41
|
+
'@ -ErrorAction SilentlyContinue
|
|
42
|
+
`;
|
|
43
|
+
export function registerWindowTools(server) {
|
|
44
|
+
server.tool('windows_window_list', 'List all visible windows with title, PID, process name, position, size, and state.', {
|
|
45
|
+
filter: z.string().optional().describe('Filter by window title (substring)'),
|
|
46
|
+
}, async ({ filter }) => {
|
|
47
|
+
const filterClause = filter
|
|
48
|
+
? `| Where-Object { $_.Title -like '*${filter.replace(/'/g, "''")}*' }`
|
|
49
|
+
: '';
|
|
50
|
+
const ps = `
|
|
51
|
+
${WIN32_TYPES}
|
|
52
|
+
$windows = [System.Collections.Generic.List[PSObject]]::new()
|
|
53
|
+
$zOrder = 0
|
|
54
|
+
[WindowManager]::EnumWindows({
|
|
55
|
+
param($hWnd, $lParam)
|
|
56
|
+
if (-not [WindowManager]::IsWindowVisible($hWnd)) { return $true }
|
|
57
|
+
$len = [WindowManager]::GetWindowTextLength($hWnd)
|
|
58
|
+
if ($len -eq 0) { return $true }
|
|
59
|
+
$sb = New-Object System.Text.StringBuilder($len + 1)
|
|
60
|
+
[WindowManager]::GetWindowText($hWnd, $sb, $sb.Capacity) | Out-Null
|
|
61
|
+
$title = $sb.ToString()
|
|
62
|
+
if (-not $title) { return $true }
|
|
63
|
+
|
|
64
|
+
$pid = [uint32]0
|
|
65
|
+
[WindowManager]::GetWindowThreadProcessId($hWnd, [ref]$pid) | Out-Null
|
|
66
|
+
$proc = Get-Process -Id $pid -ErrorAction SilentlyContinue
|
|
67
|
+
|
|
68
|
+
$rect = New-Object WindowManager+RECT
|
|
69
|
+
[WindowManager]::GetWindowRect($hWnd, [ref]$rect) | Out-Null
|
|
70
|
+
|
|
71
|
+
$state = 'Normal'
|
|
72
|
+
if ([WindowManager]::IsIconic($hWnd)) { $state = 'Minimized' }
|
|
73
|
+
elseif ([WindowManager]::IsZoomed($hWnd)) { $state = 'Maximized' }
|
|
74
|
+
|
|
75
|
+
$script:windows.Add([PSCustomObject]@{
|
|
76
|
+
ZOrder = $script:zOrder++
|
|
77
|
+
Title = $title
|
|
78
|
+
PID = $pid
|
|
79
|
+
Process = if ($proc) { $proc.ProcessName } else { '?' }
|
|
80
|
+
X = $rect.Left
|
|
81
|
+
Y = $rect.Top
|
|
82
|
+
Width = $rect.Right - $rect.Left
|
|
83
|
+
Height = $rect.Bottom - $rect.Top
|
|
84
|
+
State = $state
|
|
85
|
+
})
|
|
86
|
+
return $true
|
|
87
|
+
}, [IntPtr]::Zero) | Out-Null
|
|
88
|
+
|
|
89
|
+
$windows ${filterClause} | ConvertTo-Json -Depth 3 -Compress`;
|
|
90
|
+
const result = await runPowerShell(ps, { timeout: 10000 });
|
|
91
|
+
if (result.exitCode !== 0) {
|
|
92
|
+
return { content: [{ type: 'text', text: `Error: ${result.stderr}` }], isError: true };
|
|
93
|
+
}
|
|
94
|
+
if (!result.stdout) {
|
|
95
|
+
return { content: [{ type: 'text', text: 'No visible windows found.' }] };
|
|
96
|
+
}
|
|
97
|
+
const windows = Array.isArray(JSON.parse(result.stdout)) ? JSON.parse(result.stdout) : [JSON.parse(result.stdout)];
|
|
98
|
+
const lines = windows.map((w) => {
|
|
99
|
+
const stateIcon = w.State === 'Minimized' ? '[-]' : w.State === 'Maximized' ? '[+]' : '[ ]';
|
|
100
|
+
return `${stateIcon} ${String(w.PID).padStart(6)} ${w.Process.padEnd(20).slice(0, 20)} ${String(w.Width).padStart(5)}x${String(w.Height).padEnd(5)} (${w.X},${w.Y}) ${w.Title.slice(0, 60)}`;
|
|
101
|
+
});
|
|
102
|
+
const header = `Sta ${'PID'.padStart(6)} ${'Process'.padEnd(20)} ${'Size'.padStart(11)} Pos Title`;
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: 'text', text: `${header}\n${'─'.repeat(110)}\n${lines.join('\n')}\n\n${windows.length} windows` }],
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
server.tool('windows_window_control', 'Move, resize, minimize, maximize, restore, close, or focus a window.', {
|
|
108
|
+
title: z.string().optional().describe('Window title (substring match)'),
|
|
109
|
+
pid: z.number().optional().describe('Process ID'),
|
|
110
|
+
action: z.enum(['minimize', 'maximize', 'restore', 'close', 'focus', 'move', 'resize', 'topmost']).describe('Action'),
|
|
111
|
+
x: z.number().optional().describe('X position (for move)'),
|
|
112
|
+
y: z.number().optional().describe('Y position (for move)'),
|
|
113
|
+
width: z.number().optional().describe('Width (for resize)'),
|
|
114
|
+
height: z.number().optional().describe('Height (for resize)'),
|
|
115
|
+
topmost: z.boolean().optional().describe('Set always-on-top (for topmost action)'),
|
|
116
|
+
}, async ({ title, pid, action, x, y, width, height, topmost }) => {
|
|
117
|
+
if (!title && !pid) {
|
|
118
|
+
return { content: [{ type: 'text', text: 'Provide either title or pid.' }], isError: true };
|
|
119
|
+
}
|
|
120
|
+
const findWindow = title
|
|
121
|
+
? `
|
|
122
|
+
$target = '${title.replace(/'/g, "''")}'
|
|
123
|
+
$hWnd = [IntPtr]::Zero
|
|
124
|
+
[WindowManager]::EnumWindows({
|
|
125
|
+
param($h, $l)
|
|
126
|
+
$sb = New-Object System.Text.StringBuilder 256
|
|
127
|
+
[WindowManager]::GetWindowText($h, $sb, 256) | Out-Null
|
|
128
|
+
if ($sb.ToString() -like "*$target*" -and [WindowManager]::IsWindowVisible($h)) {
|
|
129
|
+
$script:hWnd = $h; return $false
|
|
130
|
+
}
|
|
131
|
+
return $true
|
|
132
|
+
}, [IntPtr]::Zero) | Out-Null
|
|
133
|
+
if ($hWnd -eq [IntPtr]::Zero) { throw "Window not found: $target" }`
|
|
134
|
+
: `
|
|
135
|
+
$proc = Get-Process -Id ${pid} -ErrorAction Stop
|
|
136
|
+
$hWnd = $proc.MainWindowHandle
|
|
137
|
+
if ($hWnd -eq [IntPtr]::Zero) { throw "Process ${pid} has no visible window" }`;
|
|
138
|
+
let actionCode;
|
|
139
|
+
switch (action) {
|
|
140
|
+
case 'minimize':
|
|
141
|
+
actionCode = `[WindowManager]::ShowWindow($hWnd, 6) | Out-Null; "Minimized"`;
|
|
142
|
+
break;
|
|
143
|
+
case 'maximize':
|
|
144
|
+
actionCode = `[WindowManager]::ShowWindow($hWnd, 3) | Out-Null; "Maximized"`;
|
|
145
|
+
break;
|
|
146
|
+
case 'restore':
|
|
147
|
+
actionCode = `[WindowManager]::ShowWindow($hWnd, 9) | Out-Null; "Restored"`;
|
|
148
|
+
break;
|
|
149
|
+
case 'close':
|
|
150
|
+
actionCode = `[WindowManager]::PostMessage($hWnd, [WindowManager]::WM_CLOSE, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null; "Close message sent"`;
|
|
151
|
+
break;
|
|
152
|
+
case 'focus':
|
|
153
|
+
actionCode = `[WindowManager]::ShowWindow($hWnd, 9) | Out-Null; [WindowManager]::SetForegroundWindow($hWnd) | Out-Null; "Focused"`;
|
|
154
|
+
break;
|
|
155
|
+
case 'move':
|
|
156
|
+
if (x === undefined || y === undefined) {
|
|
157
|
+
return { content: [{ type: 'text', text: 'Move requires x and y.' }], isError: true };
|
|
158
|
+
}
|
|
159
|
+
actionCode = `
|
|
160
|
+
$rect = New-Object WindowManager+RECT
|
|
161
|
+
[WindowManager]::GetWindowRect($hWnd, [ref]$rect) | Out-Null
|
|
162
|
+
$w = $rect.Right - $rect.Left; $h = $rect.Bottom - $rect.Top
|
|
163
|
+
[WindowManager]::MoveWindow($hWnd, ${x}, ${y}, $w, $h, $true) | Out-Null
|
|
164
|
+
"Moved to (${x}, ${y})"`;
|
|
165
|
+
break;
|
|
166
|
+
case 'resize':
|
|
167
|
+
if (!width || !height) {
|
|
168
|
+
return { content: [{ type: 'text', text: 'Resize requires width and height.' }], isError: true };
|
|
169
|
+
}
|
|
170
|
+
actionCode = `
|
|
171
|
+
$rect = New-Object WindowManager+RECT
|
|
172
|
+
[WindowManager]::GetWindowRect($hWnd, [ref]$rect) | Out-Null
|
|
173
|
+
[WindowManager]::MoveWindow($hWnd, $rect.Left, $rect.Top, ${width}, ${height}, $true) | Out-Null
|
|
174
|
+
"Resized to ${width}x${height}"`;
|
|
175
|
+
break;
|
|
176
|
+
case 'topmost':
|
|
177
|
+
const insertAfter = topmost !== false ? '[WindowManager]::HWND_TOPMOST' : '[WindowManager]::HWND_NOTOPMOST';
|
|
178
|
+
actionCode = `[WindowManager]::SetWindowPos($hWnd, ${insertAfter}, 0, 0, 0, 0, [WindowManager]::SWP_NOMOVE -bor [WindowManager]::SWP_NOSIZE) | Out-Null; "Topmost: ${topmost !== false}"`;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
const ps = `${WIN32_TYPES}\n${findWindow}\n${actionCode}`;
|
|
182
|
+
const result = await runPowerShell(ps, { timeout: 10000 });
|
|
183
|
+
return {
|
|
184
|
+
content: [{ type: 'text', text: result.stdout || result.stderr }],
|
|
185
|
+
isError: result.exitCode !== 0,
|
|
186
|
+
};
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=window.js.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
2
|
+
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
+
*
|
|
4
|
+
* Tools: windows_winget_search (#69), windows_winget_manage (#70), windows_winget_export (#71)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { runShell } from '../shell.js';
|
|
8
|
+
export function registerWingetTools(server) {
|
|
9
|
+
server.tool('windows_winget_search', 'Search for packages in the winget repository.', {
|
|
10
|
+
query: z.string().describe('Search query (name or ID)'),
|
|
11
|
+
source: z.enum(['winget', 'msstore', 'all']).default('all').describe('Package source'),
|
|
12
|
+
limit: z.number().default(20).describe('Max results'),
|
|
13
|
+
}, async ({ query, source, limit }) => {
|
|
14
|
+
const sourceArg = source !== 'all' ? `--source ${source}` : '';
|
|
15
|
+
const cmd = `winget search "${query}" ${sourceArg} --count ${limit} --accept-source-agreements --disable-interactivity`;
|
|
16
|
+
const result = await runShell(cmd, { shell: 'cmd', timeout: 30000 });
|
|
17
|
+
const clean = result.stdout.replace(/\0/g, '').trim();
|
|
18
|
+
return {
|
|
19
|
+
content: [{ type: 'text', text: clean || 'No packages found.' }],
|
|
20
|
+
isError: result.exitCode !== 0 && !clean,
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
server.tool('windows_winget_manage', 'Install, upgrade, or uninstall packages via winget. Also list installed or upgradable packages.', {
|
|
24
|
+
action: z.enum(['install', 'upgrade', 'uninstall', 'list', 'upgradable', 'upgrade_all']).describe('Action'),
|
|
25
|
+
id: z.string().optional().describe('Package ID (e.g. "Microsoft.VisualStudioCode")'),
|
|
26
|
+
version: z.string().optional().describe('Specific version to install'),
|
|
27
|
+
}, async ({ action, id, version }) => {
|
|
28
|
+
let cmd;
|
|
29
|
+
switch (action) {
|
|
30
|
+
case 'install':
|
|
31
|
+
if (!id)
|
|
32
|
+
return { content: [{ type: 'text', text: 'install requires id.' }], isError: true };
|
|
33
|
+
cmd = `winget install --id "${id}" ${version ? `--version "${version}"` : ''} --accept-package-agreements --accept-source-agreements --disable-interactivity`;
|
|
34
|
+
break;
|
|
35
|
+
case 'upgrade':
|
|
36
|
+
if (!id)
|
|
37
|
+
return { content: [{ type: 'text', text: 'upgrade requires id.' }], isError: true };
|
|
38
|
+
cmd = `winget upgrade --id "${id}" --accept-package-agreements --accept-source-agreements --disable-interactivity`;
|
|
39
|
+
break;
|
|
40
|
+
case 'upgrade_all':
|
|
41
|
+
cmd = `winget upgrade --all --accept-package-agreements --accept-source-agreements --disable-interactivity`;
|
|
42
|
+
break;
|
|
43
|
+
case 'uninstall':
|
|
44
|
+
if (!id)
|
|
45
|
+
return { content: [{ type: 'text', text: 'uninstall requires id.' }], isError: true };
|
|
46
|
+
cmd = `winget uninstall --id "${id}" --disable-interactivity`;
|
|
47
|
+
break;
|
|
48
|
+
case 'list':
|
|
49
|
+
cmd = `winget list --accept-source-agreements --disable-interactivity`;
|
|
50
|
+
break;
|
|
51
|
+
case 'upgradable':
|
|
52
|
+
cmd = `winget upgrade --accept-source-agreements --disable-interactivity`;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
const timeout = action === 'install' || action === 'upgrade' || action === 'upgrade_all' ? 300000 : 30000;
|
|
56
|
+
const result = await runShell(cmd, { shell: 'cmd', timeout });
|
|
57
|
+
const clean = result.stdout.replace(/\0/g, '').trim();
|
|
58
|
+
return {
|
|
59
|
+
content: [{ type: 'text', text: clean || result.stderr || `${action} completed.` }],
|
|
60
|
+
isError: result.exitCode !== 0 && !clean,
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
server.tool('windows_winget_export', 'Export installed packages to JSON or import from a JSON file.', {
|
|
64
|
+
action: z.enum(['export', 'import']).describe('Action'),
|
|
65
|
+
path: z.string().describe('File path for export/import JSON'),
|
|
66
|
+
}, async ({ action, path }) => {
|
|
67
|
+
const cmd = action === 'export'
|
|
68
|
+
? `winget export -o "${path}" --accept-source-agreements --disable-interactivity`
|
|
69
|
+
: `winget import -i "${path}" --accept-package-agreements --accept-source-agreements --disable-interactivity`;
|
|
70
|
+
const timeout = action === 'import' ? 600000 : 30000;
|
|
71
|
+
const result = await runShell(cmd, { shell: 'cmd', timeout });
|
|
72
|
+
const clean = result.stdout.replace(/\0/g, '').trim();
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: 'text', text: clean || `${action} completed: ${path}` }],
|
|
75
|
+
isError: result.exitCode !== 0 && !clean,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=winget.js.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
2
|
+
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
+
*
|
|
4
|
+
* Tools: windows_wsl_list (#66), windows_wsl_manage (#67), windows_wsl_exec (#68)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { runShell, runPowerShell } from '../shell.js';
|
|
8
|
+
export function registerWslTools(server) {
|
|
9
|
+
server.tool('windows_wsl_list', 'List installed WSL distributions with status, version, and default flag.', {}, async () => {
|
|
10
|
+
// wsl.exe outputs UTF-16; use PowerShell to decode properly
|
|
11
|
+
const ps = `$out = wsl --list --verbose 2>&1; if ($LASTEXITCODE -ne 0) { "WSL_ERROR:$out" } else { $out }`;
|
|
12
|
+
const result = await runPowerShell(ps, { timeout: 15000 });
|
|
13
|
+
const clean = result.stdout.replace(/\0/g, '').trim();
|
|
14
|
+
if (clean.startsWith('WSL_ERROR:') || result.exitCode !== 0) {
|
|
15
|
+
const msg = clean.replace('WSL_ERROR:', '').trim();
|
|
16
|
+
return { content: [{ type: 'text', text: msg || 'WSL is not installed or not available. Install with: wsl --install' }] };
|
|
17
|
+
}
|
|
18
|
+
return { content: [{ type: 'text', text: clean || 'No WSL distributions installed.' }] };
|
|
19
|
+
});
|
|
20
|
+
server.tool('windows_wsl_manage', 'Manage WSL: start, stop, shutdown, set default, export, import, or remove distros.', {
|
|
21
|
+
action: z.enum(['shutdown', 'terminate', 'set_default', 'set_version', 'export', 'import', 'unregister']).describe('Action'),
|
|
22
|
+
distro: z.string().optional().describe('Distribution name'),
|
|
23
|
+
version: z.number().optional().describe('WSL version 1 or 2 (for set_version)'),
|
|
24
|
+
path: z.string().optional().describe('File path (for export/import)'),
|
|
25
|
+
}, async ({ action, distro, version, path }) => {
|
|
26
|
+
let cmd;
|
|
27
|
+
switch (action) {
|
|
28
|
+
case 'shutdown':
|
|
29
|
+
cmd = 'wsl --shutdown';
|
|
30
|
+
break;
|
|
31
|
+
case 'terminate':
|
|
32
|
+
if (!distro)
|
|
33
|
+
return { content: [{ type: 'text', text: 'terminate requires distro.' }], isError: true };
|
|
34
|
+
cmd = `wsl --terminate ${distro}`;
|
|
35
|
+
break;
|
|
36
|
+
case 'set_default':
|
|
37
|
+
if (!distro)
|
|
38
|
+
return { content: [{ type: 'text', text: 'set_default requires distro.' }], isError: true };
|
|
39
|
+
cmd = `wsl --set-default ${distro}`;
|
|
40
|
+
break;
|
|
41
|
+
case 'set_version':
|
|
42
|
+
if (!distro || !version)
|
|
43
|
+
return { content: [{ type: 'text', text: 'set_version requires distro and version.' }], isError: true };
|
|
44
|
+
cmd = `wsl --set-version ${distro} ${version}`;
|
|
45
|
+
break;
|
|
46
|
+
case 'export':
|
|
47
|
+
if (!distro || !path)
|
|
48
|
+
return { content: [{ type: 'text', text: 'export requires distro and path.' }], isError: true };
|
|
49
|
+
cmd = `wsl --export ${distro} "${path}"`;
|
|
50
|
+
break;
|
|
51
|
+
case 'import':
|
|
52
|
+
if (!distro || !path)
|
|
53
|
+
return { content: [{ type: 'text', text: 'import requires distro and path.' }], isError: true };
|
|
54
|
+
cmd = `wsl --import ${distro} "C:\\WSL\\${distro}" "${path}"`;
|
|
55
|
+
break;
|
|
56
|
+
case 'unregister':
|
|
57
|
+
if (!distro)
|
|
58
|
+
return { content: [{ type: 'text', text: 'unregister requires distro.' }], isError: true };
|
|
59
|
+
cmd = `wsl --unregister ${distro}`;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
const result = await runShell(cmd, { shell: 'cmd', timeout: 60000 });
|
|
63
|
+
const clean = (result.stdout + '\n' + result.stderr).replace(/\0/g, '').trim();
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: 'text', text: clean || `${action} completed.` }],
|
|
66
|
+
isError: result.exitCode !== 0,
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
server.tool('windows_wsl_exec', 'Execute a command inside a WSL distribution. Returns stdout, stderr, exit code.', {
|
|
70
|
+
command: z.string().describe('Command to execute'),
|
|
71
|
+
distro: z.string().optional().describe('Distribution name (default distro if omitted)'),
|
|
72
|
+
user: z.string().optional().describe('Run as user'),
|
|
73
|
+
cwd: z.string().optional().describe('Working directory inside WSL'),
|
|
74
|
+
timeout: z.number().default(30000).describe('Timeout in ms'),
|
|
75
|
+
}, async ({ command, distro, user, cwd, timeout }) => {
|
|
76
|
+
const parts = ['wsl'];
|
|
77
|
+
if (distro)
|
|
78
|
+
parts.push('-d', distro);
|
|
79
|
+
if (user)
|
|
80
|
+
parts.push('-u', user);
|
|
81
|
+
if (cwd)
|
|
82
|
+
parts.push('--cd', cwd);
|
|
83
|
+
parts.push('--', 'bash', '-c', `"${command.replace(/"/g, '\\"')}"`);
|
|
84
|
+
const result = await runShell(parts.join(' '), { shell: 'cmd', timeout });
|
|
85
|
+
const clean = result.stdout.replace(/\0/g, '').trim();
|
|
86
|
+
const cleanErr = result.stderr.replace(/\0/g, '').trim();
|
|
87
|
+
const output = [];
|
|
88
|
+
if (clean)
|
|
89
|
+
output.push(clean);
|
|
90
|
+
if (cleanErr)
|
|
91
|
+
output.push(`[stderr]\n${cleanErr}`);
|
|
92
|
+
output.push(`[exit code: ${result.exitCode}]`);
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: 'text', text: output.join('\n\n') }],
|
|
95
|
+
isError: result.exitCode !== 0,
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=wsl.js.map
|
package/docs/API.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
3
|
+
SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
# FILE INFORMATION
|
|
6
|
+
DEFGROUP: mcp_windows.Documentation
|
|
7
|
+
PATH: /docs/API.md
|
|
8
|
+
VERSION: 01.00.00
|
|
9
|
+
BRIEF: MCP tool reference documentation
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
# API Reference
|
|
13
|
+
|
|
14
|
+
All tools accept an optional `connection` parameter to target a specific named connection. If omitted, the default connection is used.
|
|
15
|
+
|
|
16
|
+
## Example Resources
|
|
17
|
+
|
|
18
|
+
> Replace these example tools with your actual API tools.
|
|
19
|
+
|
|
20
|
+
### `example_resources_list`
|
|
21
|
+
List resources with optional search.
|
|
22
|
+
|
|
23
|
+
| Parameter | Type | Required | Description |
|
|
24
|
+
|-----------|------|----------|-------------|
|
|
25
|
+
| `search` | string | No | Search query |
|
|
26
|
+
| `limit` | number | No | Max results |
|
|
27
|
+
| `page` | number | No | Page number (0-based) |
|
|
28
|
+
|
|
29
|
+
### `example_resource_get`
|
|
30
|
+
Get a single resource by ID.
|
|
31
|
+
|
|
32
|
+
| Parameter | Type | Required | Description |
|
|
33
|
+
|-----------|------|----------|-------------|
|
|
34
|
+
| `id` | number | Yes | Resource ID |
|
|
35
|
+
|
|
36
|
+
### `example_resource_create`
|
|
37
|
+
Create a new resource.
|
|
38
|
+
|
|
39
|
+
| Parameter | Type | Required | Description |
|
|
40
|
+
|-----------|------|----------|-------------|
|
|
41
|
+
| `name` | string | Yes | Resource name |
|
|
42
|
+
| `description` | string | No | Resource description |
|
|
43
|
+
|
|
44
|
+
## Generic
|
|
45
|
+
|
|
46
|
+
### `api_request`
|
|
47
|
+
Make a raw API request to any endpoint.
|
|
48
|
+
|
|
49
|
+
| Parameter | Type | Required | Description |
|
|
50
|
+
|-----------|------|----------|-------------|
|
|
51
|
+
| `method` | `"GET"` / `"POST"` / `"PUT"` / `"PATCH"` / `"DELETE"` | Yes | HTTP method |
|
|
52
|
+
| `endpoint` | string | Yes | API path |
|
|
53
|
+
| `body` | object | No | Request body |
|
|
54
|
+
| `params` | object | No | Query parameters |
|
|
55
|
+
|
|
56
|
+
### `list_connections`
|
|
57
|
+
List all configured connections. No parameters.
|
|
58
|
+
|
|
59
|
+
## Revision History
|
|
60
|
+
|
|
61
|
+
| Date | Version | Author | Notes |
|
|
62
|
+
| --- | --- | --- | --- |
|
|
63
|
+
| 2026-05-07 | 0.0.1 | jmiller | Initial template API reference |
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
3
|
+
SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
# FILE INFORMATION
|
|
6
|
+
DEFGROUP: mcp_windows.Documentation
|
|
7
|
+
PATH: /docs/ARCHITECTURE.md
|
|
8
|
+
VERSION: 01.00.00
|
|
9
|
+
BRIEF: Architecture overview and design decisions
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
# Architecture
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
mcp_windows is a Model Context Protocol (MCP) server that bridges AI assistants with a REST API.
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
AI Assistant <--> MCP (stdio) <--> ApiClient <--> REST API
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Components
|
|
23
|
+
|
|
24
|
+
### `src/index.ts` — Server Entry Point
|
|
25
|
+
|
|
26
|
+
Registers all MCP tools with `McpServer` from `@modelcontextprotocol/sdk`. Each tool maps to one or more API endpoints. Uses Zod schemas for input validation.
|
|
27
|
+
|
|
28
|
+
Includes shared helpers:
|
|
29
|
+
- `formatResponse()` — normalizes error/success responses into MCP text content
|
|
30
|
+
- `paginationQuery()` — builds pagination query params
|
|
31
|
+
- `ConnectionParam` / `PaginationParams` — reusable Zod parameter spreads
|
|
32
|
+
|
|
33
|
+
### `src/client.ts` — HTTP Client
|
|
34
|
+
|
|
35
|
+
The `ApiClient` class handles all HTTP communication:
|
|
36
|
+
- Uses `node:https` / `node:http` (not `fetch`) for reliable self-signed cert support
|
|
37
|
+
- Supports GET, POST, PUT, PATCH, DELETE
|
|
38
|
+
- JSON serialization/deserialization with error handling
|
|
39
|
+
|
|
40
|
+
### `src/config.ts` — Configuration Loader
|
|
41
|
+
|
|
42
|
+
Loads connection details from `~/.<project>.json`. Supports multiple named connections with a configurable default.
|
|
43
|
+
|
|
44
|
+
### `src/types.ts` — Type Definitions
|
|
45
|
+
|
|
46
|
+
TypeScript interfaces for `ApiConnection`, `ApiConfig`, and `ApiResponse`.
|
|
47
|
+
|
|
48
|
+
### `scripts/setup.mjs` — Interactive Setup
|
|
49
|
+
|
|
50
|
+
Node.js script using `readline/promises` for interactive config creation.
|
|
51
|
+
|
|
52
|
+
## Design Decisions
|
|
53
|
+
|
|
54
|
+
### Why `node:https` instead of `fetch`?
|
|
55
|
+
|
|
56
|
+
Node.js 24's built-in `fetch` does not honor self-signed certificate bypass. The classic `node:https` module with `rejectUnauthorized: false` works reliably across all Node.js versions.
|
|
57
|
+
|
|
58
|
+
### Why multiple named connections?
|
|
59
|
+
|
|
60
|
+
Multi-instance support is a core use case — managing staging, production, and dev environments from a single MCP server.
|
|
61
|
+
|
|
62
|
+
## Data Flow
|
|
63
|
+
|
|
64
|
+
1. AI assistant sends a tool call via MCP stdio transport
|
|
65
|
+
2. `index.ts` validates parameters with Zod and resolves the connection
|
|
66
|
+
3. `ApiClient` constructs the API URL, attaches auth headers, and makes the HTTP request
|
|
67
|
+
4. Response is parsed as JSON and returned as MCP tool output
|
|
68
|
+
|
|
69
|
+
## Revision History
|
|
70
|
+
|
|
71
|
+
| Date | Version | Author | Notes |
|
|
72
|
+
| --- | --- | --- | --- |
|
|
73
|
+
| 2026-05-07 | 0.0.1 | jmiller | Initial architecture document |
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
3
|
+
SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
# FILE INFORMATION
|
|
6
|
+
DEFGROUP: mcp_windows.Documentation
|
|
7
|
+
PATH: /docs/INSTALLATION.md
|
|
8
|
+
VERSION: 01.00.00
|
|
9
|
+
BRIEF: Installation and setup instructions
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
# Installation
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
- **Node.js** 20.0.0 or later
|
|
17
|
+
- **npm** (included with Node.js)
|
|
18
|
+
- Access to the target API with valid credentials
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
git clone https://git.mokoconsulting.tech/MokoConsulting/mcp_windows.git
|
|
24
|
+
cd mcp_windows
|
|
25
|
+
npm install
|
|
26
|
+
npm run build
|
|
27
|
+
npm run setup
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The setup wizard will prompt for:
|
|
31
|
+
|
|
32
|
+
1. **Connection name** — a label for this instance (e.g. `production`, `staging`)
|
|
33
|
+
2. **API URL** — the base URL of the instance
|
|
34
|
+
3. **API key/token** — authentication credentials
|
|
35
|
+
4. **TLS verification** — whether to skip certificate verification (for self-signed certs)
|
|
36
|
+
|
|
37
|
+
Run `npm run setup` again to add more connections.
|
|
38
|
+
|
|
39
|
+
## Register with Claude Code
|
|
40
|
+
|
|
41
|
+
Add to your Claude Code MCP settings (`~/.claude.json` or project `.mcp.json`):
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"mcpServers": {
|
|
46
|
+
"mcp_windows": {
|
|
47
|
+
"type": "stdio",
|
|
48
|
+
"command": "node",
|
|
49
|
+
"args": ["/path/to/mcp_windows/dist/index.js"]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Restart Claude Code after adding the server.
|
|
56
|
+
|
|
57
|
+
## Configuration File
|
|
58
|
+
|
|
59
|
+
The config is stored at `~/.mcp_windows.json`:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"defaultConnection": "production",
|
|
64
|
+
"connections": {
|
|
65
|
+
"production": {
|
|
66
|
+
"baseUrl": "https://api.example.com",
|
|
67
|
+
"apiKey": "your-api-key"
|
|
68
|
+
},
|
|
69
|
+
"staging": {
|
|
70
|
+
"baseUrl": "https://api-staging.example.com",
|
|
71
|
+
"apiKey": "your-staging-key",
|
|
72
|
+
"insecure": true
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
You can also set the `MCP_WINDOWS_CONFIG` environment variable to use a config file at a custom path.
|
|
79
|
+
|
|
80
|
+
## Verification
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
npm start
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
If configured correctly, the server will start listening on stdio.
|
|
87
|
+
|
|
88
|
+
## Troubleshooting
|
|
89
|
+
|
|
90
|
+
### "Failed to load config" error
|
|
91
|
+
Run `npm run setup` to create the config file.
|
|
92
|
+
|
|
93
|
+
### Connection errors
|
|
94
|
+
- Verify the API is reachable from your machine
|
|
95
|
+
- For self-signed certs, set `"insecure": true`
|
|
96
|
+
- Ensure the API key/token is valid
|
|
97
|
+
|
|
98
|
+
## Revision History
|
|
99
|
+
|
|
100
|
+
| Date | Version | Author | Notes |
|
|
101
|
+
| --- | --- | --- | --- |
|
|
102
|
+
| 2026-05-07 | 0.0.1 | jmiller | Initial installation guide |
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
2
|
+
SPDX-License-Identifier: GPL-3.0-or-later -->
|
|
3
|
+
|
|
4
|
+
# mcp_windows Documentation
|
|
5
|
+
|
|
6
|
+
See the [README](../README.md) for quick start, customization guide, and tool patterns.
|
|
7
|
+
|
|
8
|
+
## Documents
|
|
9
|
+
|
|
10
|
+
- [INSTALLATION.md](./INSTALLATION.md) — Prerequisites, install, setup, troubleshooting
|
|
11
|
+
- [ARCHITECTURE.md](./ARCHITECTURE.md) — Component overview, design decisions, data flow
|
|
12
|
+
- [API.md](./API.md) — Full MCP tool reference with parameter tables
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mokoconsulting/mcp-windows",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "MCP server for Windows desktop system operations",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp-windows": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"lint": "eslint src/",
|
|
15
|
+
"setup": "node scripts/setup.mjs",
|
|
16
|
+
"clean": "rm -rf dist/"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
20
|
+
"zod": "^3.24.4"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.15.3",
|
|
24
|
+
"typescript": "^5.8.3"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20.0.0"
|
|
28
|
+
},
|
|
29
|
+
"license": "GPL-3.0-or-later",
|
|
30
|
+
"author": "Moko Consulting <hello@mokoconsulting.tech>",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://git.mokoconsulting.tech/MokoConsulting/mcp-windows.git"
|
|
34
|
+
}
|
|
35
|
+
}
|