Skip to content

Commit 2c0ec03

Browse files
ADO Lens 0.5.1
ADO Lens 0.5.1
2 parents 52897da + 60fcfb2 commit 2c0ec03

12 files changed

Lines changed: 213 additions & 8 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 0.5.1 — 2026-10-15
4+
5+
- An icon: the program, the installer, Settings → Apps, the Start menu and the Claude Desktop extension.
6+
- Start menu folder "ADO Lens": settings (`adolens setup`), status, skills for Claude Desktop, uninstall.
7+
- The installer puts the program folder on the user's PATH: `adolens` works in any new terminal.
8+
- Uninstall asks whether to remove the stored PATs and the settings and cache too (default: keep them); it also takes
9+
the program off the PATH. `adolens logout --all` removes every stored PAT.
10+
311
## 0.5.0 — 2026-10-15
412

513
Tests, templates, and two more ways to install.

‎README.md‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<img src="packaging/icon/icon.png" alt="ADO Lens" width="96" align="right">
2+
13
# ADO Lens for Azure DevOps — an MCP server for Claude
24

35
[![CI](https://github.com/willowdev-code/ado-lens/actions/workflows/ci.yml/badge.svg)](https://github.com/willowdev-code/ado-lens/actions/workflows/ci.yml)
@@ -47,8 +49,12 @@ The install package is not part of the repository (`dist\` is excluded by `.giti
4749
administrator rights. It asks for the Azure DevOps link and the PAT (checked before anything is installed), who uses
4850
it (Product Owner / developer / everything), installs the skills and registers ADO Lens in Claude; an update skips the
4951
questions. Until the program is signed, Windows SmartScreen may show "Windows protected your PC" for a file downloaded
50-
in a browser: *More info → Run anyway* (or use the one-line install above, which avoids it). Uninstall it from
51-
*Settings → Apps*.
52+
in a browser: *More info → Run anyway* (or use the one-line install above, which avoids it).
53+
54+
After installing, the Start menu has an **ADO Lens** folder: *settings* (mode, environments, another connection —
55+
`adolens setup` in a console), *status* (is everything working) and the skills for Claude Desktop; `adolens` works in
56+
any new terminal. Uninstall from *Settings → Apps → ADO Lens* (or the Start menu): it removes the program, its Claude
57+
registrations and skills, and asks whether to remove the stored PATs and settings too (by default they stay).
5258

5359
**Claude Desktop only (extension).** `ado-lens-X.Y.Z.mcpb` from **Releases**: open it with Claude Desktop (or drag it
5460
into *Settings → Extensions*) and fill in the project link and the PAT, which Claude Desktop keeps in the system's secure
@@ -103,7 +109,7 @@ mentions it once per session; say "update ADO Lens" and `ado_upgrade` downloads
103109
installer in its own window. From a terminal: `adolens upgrade` shows what is new, `adolens upgrade --install` installs
104110
it (`--pre` includes test releases). Settings, PATs and metadata are kept; Claude may stay open.
105111

106-
Uninstall: `uninstall.ps1` in the installation folder (removes the Claude registrations and skills of this installation,
112+
Uninstall (ZIP and one-line installs): `uninstall.ps1` in the installation folder (removes the Claude registrations and skills of this installation,
107113
asks about the stored PATs and the local data).
108114

109115
### The PAT

‎README.pl.md‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<img src="packaging/icon/icon.png" alt="ADO Lens" width="96" align="right">
2+
13
# ADO Lens for Azure DevOps — serwer MCP dla Claude'a
24

35
[![CI](https://github.com/willowdev-code/ado-lens/actions/workflows/ci.yml/badge.svg)](https://github.com/willowdev-code/ado-lens/actions/workflows/ci.yml)
@@ -48,7 +50,11 @@ administratora. Pyta o link do Azure DevOps i PAT (sprawdzane, zanim cokolwiek s
4850
Owner / programista / wszystko), instaluje skille i rejestruje ADO Lens w Claudzie; aktualizacja pomija pytania. Dopóki
4951
program nie jest podpisany, Windows SmartScreen może przy pliku pobranym przeglądarką pokazać „System Windows ochronił
5052
ten komputer”: *Więcej informacji → Uruchom mimo to* (albo użyj instalacji jedną linijką powyżej, która tego unika).
51-
Odinstalowanie: *Ustawienia → Aplikacje*.
53+
54+
Po instalacji w menu Start jest folder **ADO Lens**: *ustawienia* (tryb, środowiska, kolejne połączenie — `adolens setup`
55+
w konsoli), *status* (czy wszystko działa) i skille dla Claude Desktop; `adolens` działa w każdym nowym terminalu.
56+
Odinstalowanie: *Ustawienia → Aplikacje → ADO Lens* (albo z menu Start) — usuwa program, jego rejestracje w Claudzie
57+
i skille, i pyta, czy usunąć też zapisane PAT-y i ustawienia (domyślnie zostają).
5258

5359
**Tylko Claude Desktop (rozszerzenie).** `ado-lens-X.Y.Z.mcpb` z **Releases**: otwórz go w Claude Desktop (albo
5460
przeciągnij do *Settings → Extensions*) i wpisz link do projektu oraz PAT, który Claude Desktop trzyma w bezpiecznym
@@ -105,7 +111,7 @@ w sesji; wystarczy powiedzieć „zaktualizuj ADO Lens”, a `ado_upgrade` pobie
105111
instalator w osobnym oknie. Z terminala: `adolens upgrade` pokazuje, co nowego, `adolens upgrade --install` instaluje
106112
(`--pre` uwzględnia wydania testowe). Ustawienia, PAT-y i metadane zostają; Claude może być otwarty.
107113

108-
Deinstalacja: `uninstall.ps1` w folderze instalacji (usuwa rejestracje i skille tej instalacji w Claude, pyta o zapisane
114+
Deinstalacja (instalacja z ZIP-a i jedną linijką): `uninstall.ps1` w folderze instalacji (usuwa rejestracje i skille tej instalacji w Claude, pyta o zapisane
109115
PAT-y i dane lokalne).
110116

111117
### PAT

‎pack.ps1‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ if (-not $NoZip) {
9292
[IO.File]::WriteAllText((Join-Path $mcpbStage 'manifest.json'), $manifest, (New-Object Text.UTF8Encoding $false))
9393
Copy-Item (Join-Path $stage 'bin') $mcpbStage -Recurse
9494
Copy-Item (Join-Path $stage 'LICENSE') $mcpbStage
95+
Copy-Item (Join-Path $PSScriptRoot 'packaging\icon\icon.png') $mcpbStage
9596
$mcpb = Join-Path $OutDir "ado-lens-$version.mcpb"
9697
New-Zip $mcpbStage $mcpb $false
9798
Write-Checksum $mcpb 'mcpb'

‎packaging/icon/adolens.ico‎

19.4 KB
Binary file not shown.

‎packaging/icon/icon.png‎

14.1 KB
Loading

‎packaging/icon/make-icon.ps1‎

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<#
2+
.SYNOPSIS
3+
Draws the ADO Lens icon: a lens over three work item bars on an Azure blue tile.
4+
Writes adolens.ico (16-256 px, PNG frames) and icon.png (512 px) next to this script.
5+
#>
6+
$ErrorActionPreference = 'Stop'
7+
Add-Type -AssemblyName System.Drawing
8+
9+
function New-RoundedRect([float] $x, [float] $y, [float] $w, [float] $h, [float] $r) {
10+
$p = New-Object System.Drawing.Drawing2D.GraphicsPath
11+
$d = 2 * $r
12+
$p.AddArc($x, $y, $d, $d, 180, 90)
13+
$p.AddArc($x + $w - $d, $y, $d, $d, 270, 90)
14+
$p.AddArc($x + $w - $d, $y + $h - $d, $d, $d, 0, 90)
15+
$p.AddArc($x, $y + $h - $d, $d, $d, 90, 90)
16+
$p.CloseFigure()
17+
return $p
18+
}
19+
20+
function New-IconBitmap([int] $size) {
21+
$bmp = New-Object System.Drawing.Bitmap $size, $size, ([System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
22+
$g = [System.Drawing.Graphics]::FromImage($bmp)
23+
$g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
24+
$g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
25+
$g.Clear([System.Drawing.Color]::Transparent)
26+
$s = [float] $size
27+
28+
# Tile: Azure blue, lighter at the top.
29+
$margin = [Math]::Max(0.5, $s * 0.03)
30+
$tile = New-RoundedRect $margin $margin ($s - 2 * $margin) ($s - 2 * $margin) ($s * 0.2)
31+
$grad = New-Object System.Drawing.Drawing2D.LinearGradientBrush (New-Object System.Drawing.PointF 0, 0), (New-Object System.Drawing.PointF 0, $s),
32+
([System.Drawing.Color]::FromArgb(255, 0, 137, 230)), ([System.Drawing.Color]::FromArgb(255, 0, 90, 170))
33+
$g.FillPath($grad, $tile)
34+
35+
$white = [System.Drawing.Color]::White
36+
# Lens: a ring, centred a little up and left, with a handle to the bottom right.
37+
$cx = $s * 0.43; $cy = $s * 0.43; $r = $s * 0.24
38+
$ring = [Math]::Max(1.5, $s * 0.075)
39+
if ($size -ge 32) {
40+
# Three work item bars inside the lens (left out at small sizes, where they would blur).
41+
$bar = New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(235, 255, 255, 255))
42+
$bh = $s * 0.045
43+
foreach ($i in 0..2) {
44+
$w = $r * (1.05 - 0.25 * $i)
45+
$y = $cy - $r * 0.42 + $i * $r * 0.42 - $bh / 2
46+
$path = New-RoundedRect ($cx - $r * 0.55) $y $w $bh ($bh / 2)
47+
$g.FillPath($bar, $path)
48+
}
49+
}
50+
$pen = New-Object System.Drawing.Pen $white, $ring
51+
$g.DrawEllipse($pen, $cx - $r, $cy - $r, 2 * $r, 2 * $r)
52+
$handle = New-Object System.Drawing.Pen $white, ([Math]::Max(2, $s * 0.11))
53+
$handle.StartCap = [System.Drawing.Drawing2D.LineCap]::Round
54+
$handle.EndCap = [System.Drawing.Drawing2D.LineCap]::Round
55+
$a = 0.7071 * ($r + $ring / 2)
56+
$g.DrawLine($handle, $cx + $a, $cy + $a, $s * 0.76, $s * 0.76)
57+
$g.Dispose()
58+
return $bmp
59+
}
60+
61+
$dir = $PSScriptRoot
62+
$sizes = 16, 20, 24, 32, 40, 48, 64, 128, 256
63+
$frames = foreach ($n in $sizes) {
64+
$bmp = New-IconBitmap $n
65+
$ms = New-Object System.IO.MemoryStream
66+
$bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
67+
$bmp.Dispose()
68+
, $ms.ToArray()
69+
}
70+
71+
# ICO: header, one directory entry per size, then the PNG frames.
72+
$out = New-Object System.IO.MemoryStream
73+
$w = New-Object System.IO.BinaryWriter $out
74+
$w.Write([UInt16]0); $w.Write([UInt16]1); $w.Write([UInt16]$sizes.Count)
75+
$offset = 6 + 16 * $sizes.Count
76+
for ($i = 0; $i -lt $sizes.Count; $i++) {
77+
$n = $sizes[$i]
78+
$dim = if ($n -ge 256) { 0 } else { $n }
79+
$w.Write([byte]$dim); $w.Write([byte]$dim); $w.Write([byte]0); $w.Write([byte]0)
80+
$w.Write([UInt16]1); $w.Write([UInt16]32)
81+
$w.Write([UInt32]$frames[$i].Length); $w.Write([UInt32]$offset)
82+
$offset += $frames[$i].Length
83+
}
84+
foreach ($f in $frames) { $w.Write($f) }
85+
$w.Flush()
86+
[IO.File]::WriteAllBytes((Join-Path $dir 'adolens.ico'), $out.ToArray())
87+
88+
$big = New-IconBitmap 512
89+
$big.Save((Join-Path $dir 'icon.png'), [System.Drawing.Imaging.ImageFormat]::Png)
90+
$big.Dispose()
91+
Write-Host "written adolens.ico and icon.png in $dir"

‎packaging/inno/ado-lens.iss‎

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ AppSupportURL=https://github.com/willowdev-code/ado-lens/issues
2626
DefaultDirName={localappdata}\Programs\ADO Lens
2727
DisableDirPage=yes
2828
DisableProgramGroupPage=yes
29+
DefaultGroupName=ADO Lens
2930
DisableReadyPage=yes
31+
SetupIconFile={#SourcePath}..\icon\adolens.ico
32+
; The program folder goes on the user's PATH, so "adolens" works in any new terminal.
33+
ChangesEnvironment=yes
3034
PrivilegesRequired=lowest
3135
ArchitecturesAllowed=x64compatible
3236
ArchitecturesInstallIn64BitMode=x64compatible
@@ -52,6 +56,19 @@ Source: "{#DesktopSkills}\*.zip"; DestDir: "{app}\skills-for-claude-desktop"; Fl
5256
; Claude Code reads skills from %USERPROFILE%\.claude\skills (only when Claude Code is there); removed on uninstall.
5357
Source: "{#Source}\skills\*"; DestDir: "{%USERPROFILE}\.claude\skills"; Flags: recursesubdirs ignoreversion; Check: HasClaudeCode
5458

59+
[Icons]
60+
; Start menu: settings and status open in a console that stays open (adolens commands work there too).
61+
Name: "{group}\{cm:IconSettings}"; Filename: "{cmd}"; Parameters: "/k """"{app}\bin\adolens.exe"" setup"""; WorkingDir: "{app}"; IconFilename: "{app}\bin\adolens.exe"
62+
Name: "{group}\{cm:IconStatus}"; Filename: "{cmd}"; Parameters: "/k """"{app}\bin\adolens.exe"" status"""; WorkingDir: "{app}"; IconFilename: "{app}\bin\adolens.exe"
63+
Name: "{group}\{cm:IconSkills}"; Filename: "{app}\skills-for-claude-desktop"
64+
Name: "{group}\{cm:UninstallProgram,ADO Lens}"; Filename: "{uninstallexe}"; IconFilename: "{app}\bin\adolens.exe"
65+
66+
[Registry]
67+
Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}\bin"; Check: NeedsAddPath(ExpandConstant('{app}\bin'))
68+
69+
[UninstallDelete]
70+
Type: files; Name: "{app}\bin\*.old"
71+
5572
[UninstallRun]
5673
Filename: "{app}\bin\adolens.exe"; Parameters: "unregister"; Flags: runhidden waituntilterminated; RunOnceId: "unregister"
5774

@@ -60,6 +77,14 @@ Filename: "{app}\skills-for-claude-desktop"; Description: "{cm:OpenSkills}"; Fla
6077
Filename: "https://github.com/willowdev-code/ado-lens#readme"; Description: "{cm:OpenReadme}"; Flags: postinstall shellexec skipifsilent unchecked
6178

6279
[CustomMessages]
80+
en.IconSettings=ADO Lens - settings
81+
en.IconStatus=ADO Lens - status
82+
en.IconSkills=ADO Lens - skills for Claude Desktop
83+
en.RemoveData=Also remove the stored personal access tokens (Windows Credential Manager) and the settings and cache of ADO Lens?%n%nChoose No to keep them for a later installation.
84+
pl.IconSettings=ADO Lens - ustawienia
85+
pl.IconStatus=ADO Lens - status
86+
pl.IconSkills=ADO Lens - skille dla Claude Desktop
87+
pl.RemoveData=Usunąć też zapisane tokeny dostępu (Menedżer poświadczeń Windows) oraz ustawienia i pamięć podręczną ADO Lens?%n%nWybierz Nie, aby zachować je na potrzeby ponownej instalacji.
6388
en.ConnTitle=Azure DevOps
6489
en.ConnSub=Where your work items are
6590
en.ConnText=Paste a link to your Azure DevOps project from the browser (for example https://dev.azure.com/contoso/Sales), or the organization name.
@@ -119,6 +144,64 @@ var
119144
function SetEnvironmentVariable(lpName: String; lpValue: String): Boolean;
120145
external 'SetEnvironmentVariableW@kernel32.dll stdcall';
121146
147+
{ Whether a folder is missing from the user's PATH (compared without case and trailing backslash). }
148+
function NeedsAddPath(Dir: String): Boolean;
149+
var
150+
Path: String;
151+
begin
152+
if not RegQueryStringValue(HKCU, 'Environment', 'Path', Path) then
153+
begin
154+
Result := True;
155+
Exit;
156+
end;
157+
Result := Pos(';' + Lowercase(RemoveBackslashUnlessRoot(Dir)) + ';', ';' + Lowercase(Path) + ';') = 0;
158+
end;
159+
160+
procedure RemoveFromPath(Dir: String);
161+
var
162+
Path, Item, Kept: String;
163+
P: Integer;
164+
begin
165+
if not RegQueryStringValue(HKCU, 'Environment', 'Path', Path) then Exit;
166+
Kept := '';
167+
Path := Path + ';';
168+
while Path <> '' do
169+
begin
170+
P := Pos(';', Path);
171+
Item := Copy(Path, 1, P - 1);
172+
Delete(Path, 1, P);
173+
if (Item <> '') and (Lowercase(RemoveBackslashUnlessRoot(Item)) <> Lowercase(RemoveBackslashUnlessRoot(Dir))) then
174+
begin
175+
if Kept <> '' then Kept := Kept + ';';
176+
Kept := Kept + Item;
177+
end;
178+
end;
179+
RegWriteExpandStringValue(HKCU, 'Environment', 'Path', Kept);
180+
end;
181+
182+
var
183+
RemoveUserData: Boolean;
184+
185+
{ Before the files go: ask whether to remove the stored PATs and the local data (default: keep them), and sign out
186+
with the program while it is still there. After: take the program folder off the PATH and delete the data. }
187+
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
188+
var
189+
Code: Integer;
190+
begin
191+
if CurUninstallStep = usUninstall then
192+
begin
193+
RemoveUserData := not UninstallSilent and
194+
(MsgBox(CustomMessage('RemoveData'), mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES);
195+
if RemoveUserData then
196+
Exec(ExpandConstant('{app}\bin\adolens.exe'), 'logout --all', '', SW_HIDE, ewWaitUntilTerminated, Code);
197+
end
198+
else if CurUninstallStep = usPostUninstall then
199+
begin
200+
RemoveFromPath(ExpandConstant('{app}\bin'));
201+
if RemoveUserData then DelTree(ExpandConstant('{localappdata}\ado-lens'), True, True, True);
202+
end;
203+
end;
204+
122205
function HasClaudeCode: Boolean;
123206
begin
124207
Result := DirExists(ExpandConstant('{%USERPROFILE}\.claude'));

‎packaging/mcpb/manifest.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"documentation": "https://github.com/willowdev-code/ado-lens#readme",
1818
"support": "https://github.com/willowdev-code/ado-lens/issues",
1919
"license": "MIT",
20+
"icon": "icon.png",
2021
"keywords": ["azure devops", "work items", "sprint", "wiki", "tfvc", "git", "pull requests"],
2122
"server": {
2223
"type": "binary",

‎src/AdoLens/AdoLens.csproj‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
1313
<TieredPGO>true</TieredPGO>
1414
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
15+
<!-- Drawn by packaging/icon/make-icon.ps1; shown in Explorer, Settings -> Apps and the Start menu. -->
16+
<ApplicationIcon>..\..\packaging\icon\adolens.ico</ApplicationIcon>
1517
</PropertyGroup>
1618

1719
<PropertyGroup>
@@ -21,7 +23,7 @@
2123
<AssemblyTitle>ADO Lens for Azure DevOps</AssemblyTitle>
2224
<Description>Azure DevOps (work items, boards, wiki, Git and TFVC, pipelines) served to AI assistants over MCP</Description>
2325
<Copyright>Copyright © 2026 WillowDev</Copyright>
24-
<Version>0.5.0</Version>
26+
<Version>0.5.1</Version>
2527
</PropertyGroup>
2628

2729
<ItemGroup>

0 commit comments

Comments
 (0)