-
MCP Tool Explorer
To work with Model Context Protocol (MCP) servers, I created a VS Code extension for inspecting and testing.
This extension connects to any MCP server, browse its capabilities, call tools with live input forms, read resources, and render prompts. All without leaving your editor.

https://github.com/jurgen178/mcp-tool-explorer
Features
Server Management
- Auto-discovery — automatically finds servers defined in
.vscode/mcp.jsonor themcp.serversworkspace setting - Manual registration — add any server on the fly via the Add Server dialog
- All three transports —
stdio, SSE, and Streamable HTTP
Tools
- Browse all tools exposed by a server with their descriptions and parameter schemas
- Form view — auto-generated input form with type-aware fields (text, number, boolean toggle, enum select)
- JSON view — write raw JSON arguments with live validation hints (missing required fields, unknown properties)
- Run tools and see syntax-highlighted results
- Previous calls — the last 6 calls per tool are shown inline with one-click re-run
Resources
- List all resources and read their contents
- Results rendered with syntax highlighting
Prompts
- Browse and render prompts with argument input support
Request History
- A dedicated History tab records every tool call, resource read, and prompt render
- See timestamp, duration, status (success / error), and expand to inspect the request arguments and response
- Re-run any past tool call directly from the timeline
JSON Viewer
- Syntax-highlighted JSON output (keys, strings, numbers, booleans, nulls each in distinct colours)
- Copy to clipboard button appears on hover over any result
Getting Started
Installation
Install from the VS Code Marketplace, or build from source (see Building).

Opening the Explorer
- Run
MCP: Open MCP Tool Explorerfrom the Command Palette (Ctrl+Shift+P)
Auto-discovery
If your workspace has a
.vscode/mcp.jsonfile, servers are discovered automatically when the extension activates. Example:{ "servers": { "my-stdio-server": { "type": "stdio", "command": "node", "args": ["./server/index.js"] }, "my-http-server": { "type": "http", "url": "http://localhost:3000/mcp" }, "my-sse-server": { "type": "sse", "url": "http://localhost:3001/sse" } } }Adding a Server Manually
Click + Add Server in the sidebar and fill in the connection details. Manually added servers persist for the lifetime of the VS Code window.
Transports
Type Config key Description stdiocommand,args,env,cwdSpawns a local process httpurl,headersStreamable HTTP (MCP 2025-03 spec) sseurl,headersServer-Sent Events (legacy) For
stdioservers, the working directory defaults to the workspace root so relative paths incommandresolve correctly.
Building
# Install dependencies npm install # Build (webview + extension) npm run build # Watch mode (extension only) npm run watch:extension # Package as .vsix npm run packageThe webview is a Vite + React app located in
webview-ui/. Runningnpm run buildat the root builds both the webview and the extension host automatically.
Project Structure
src/ extension.ts # Extension entry point types.ts # Extension-side types mcp/ McpClientManager.ts # MCP client connections (all transports) McpConfigDiscovery.ts # Server auto-discovery panels/ McpToolExplorerPanel.ts # WebView panel & message bridge webview-ui/ src/ App.tsx # Root component & state management components/ Sidebar.tsx # Server list & connection controls ToolsPanel.tsx # Tools tab ResourcesPanel.tsx # Resources tab PromptsPanel.tsx # Prompts tab HistoryPanel.tsx # History timeline tab JsonViewer.tsx # Syntax-highlighted JSON renderer AddServerModal.tsx # Add Server dialog
Requirements
- VS Code 1.85 or later
- Node.js 18+ (for building from source)
License
MIT
- Auto-discovery — automatically finds servers defined in
-
Lossless Exposure & Contrast Adjustment in JPEG10
Lossless Tonal Adjustments in JPEG's DCT Domain: Exposure Compensation and Multi-Band Contrast
Most JPEG workflows treat exposure (brightness) and contrast as inherently "lossy": decode pixels, apply curves, then re-encode. That approach works, but it always introduces an additional step of quantization error.
In this github fork of the IJG JPEG-10 code, I added two options to
jpegtranthat operate directly on quantized DCT coefficients:-exposure-comp EV-contrast DC LOW MID HIGH
Both are applied during transcoding, so they combine naturally with existing
jpegtranoperations such as rotation, flipping, cropping, marker copying, and progressive conversion.https://github.com/jurgen178/jpeg10
Download Windows x64 binary: jpegtran.zip
Quick Usage
jpegtran [standard options] [-exposure-comp EV] [-contrast DC LOW MID HIGH] input.jpg output.jpgExamples:
# Brighten by 1 stop jpegtran -copy all -exposure-comp 1 input.jpg output.jpg # Darken by 0.5 stops jpegtran -copy all -exposure-comp -0.5 input.jpg output.jpg # Contrast (uniform: DC=LOW=MID=HIGH) jpegtran -copy all -contrast -1 -1 -1 -1 input.jpg out-contrast-u-1.jpg jpegtran -copy all -contrast -0.5 -0.5 -0.5 -0.5 input.jpg out-contrast-u-0.5.jpg jpegtran -copy all -contrast 0.5 0.5 0.5 0.5 input.jpg out-contrast-u+0.5.jpg jpegtran -copy all -contrast 1 1 1 1 input.jpg out-contrast-u+1.jpg # Contrast (band-specific examples) jpegtran -copy all -contrast 0 0 0.6 0 input.jpg out-contrast-mid+0.6.jpg jpegtran -copy all -contrast 0 0 0 0.4 input.jpg out-contrast-high+0.4.jpg jpegtran -copy all -contrast 0 0.4 0 0 input.jpg out-contrast-low+0.4.jpg # Combine: rotate 90°, brighten 0.5 EV, and add uniform contrast +0.5 jpegtran -copy all -rot 90 -exposure-comp 0.5 -contrast 0.5 0.5 0.5 0.5 input.jpg output.jpgBoth switches accept fractional values. Practical ranges:
Option Practical range Neutral -exposure-comp EV-3 … +3 0 -contrast DC LOW MID HIGH-2 … +2 0 Integrated into cPicture with live preview:
Background: DCT Coefficient Basics
A JPEG image is encoded as a grid of DCT blocks (with 8×8 Elements in size). Each block has one DC coefficient and 63 AC coefficients. But each MCU might have more than one block depending on the color subsampling.
-
DC[0] represents the (level-shifted) average sample value of the block. The relationship to pixel mean is:
$$\mu = \frac{DC_\text{unquant}}{N} + \text{center}$$
where $N$ is the DCT block size of 8 and $\text{center} = 2^{\text{precision}-1}$ (e.g. 128 for 8‑bit).
-
AC[1..N²−1] represent spatial frequency components (texture, edges, contrast).
Both DC and AC are stored quantized: the actual stored integer is $\text{round}(\text{value} / Q_k)$, where $Q_k$ is the quantization step for coefficient $k$.
-exposure-comp EV— Exposure CompensationExposure compensation from -2EV to +2EV:
Concept
A photographic EV step corresponds to doubling (or halving) the amount of light. Applied in linear light:
$$\text{gain} = 2^{EV}$$
Because JPEG samples are gamma-coded (sRGB), pixel values cannot be multiplied directly. Instead:
- Estimate a representative level from the DC blocks.
- Compute the equivalent additive pixel-domain offset by applying the gain in linear light at that reference level.
- Translate the offset into a quantized DC delta.
- Add the delta to every DC coefficient.
Only DC is modified. AC coefficients are not modified, so local contrast and texture are preserved.
Reference Level — Log-Average
A geometric mean (log-average) of all block mean levels is used as the exposure reference:
$$\bar{L} = \exp\!\left(\frac{1}{B}\sum_{i=1}^{B} \ln(L_i + 1)\right) - 1$$
where $L_i$ is the intensity mean of block $i$ (clamped to $[0, \text{MAX}]$) and $B$ is the total number of blocks.
sRGB Linearisation
The gain is applied in linear light:
$$u_\text{ref} = \frac{\bar{L}}{\text{MAX}}$$
$$u_\text{ref,lin} = f_\text{lin}(u_\text{ref})$$
$$u_\text{new,lin} = \min(u_\text{ref,lin} \cdot \text{gain},\; 1.0)$$
$$u_\text{new} = f_\text{sRGB}(u_\text{new,lin})$$
The sRGB transfer functions used:
$$f_\text{lin}(u) = \begin{cases} u / 12.92 & u \le 0.04045 \\ \left(\dfrac{u + 0.055}{1.055}\right)^{2.4} & u > 0.04045 \end{cases}$$
$$f_\text{sRGB}(u) = \begin{cases} 12.92\,u & u \le 0.0031308 \\ 1.055\,u^{1/2.4} - 0.055 & u > 0.0031308 \end{cases}$$
Pixel-Domain Offset → Quantized DC Delta
$$\Delta_\text{samples} = (u_\text{new} - u_\text{ref}) \cdot \text{MAX}$$
Clamped to available headroom/shadow room to limit clipping, then converted to a quantized DC delta:
$$\Delta_{DC} = \text{round}\!\left(\frac{\Delta_\text{samples} \cdot N}{Q_0}\right)$$
where $N$ is the DCT block size and $Q_0$ is the DC quantization step.
Component Policy
Color space Components adjusted YCbCr, BG_YCC, YCCK Luma only (component 0) RGB/BG_RGB + subtract-green transform Green/base only (component 1) CMYK, all others All components For CMYK and YCCK the delta is computed in an inverted intensity domain ($I = \text{MAX} - \text{sample}$) so that +EV brightens and −EV darkens.
-contrast DC LOW MID HIGH— Contrast AdjustmentContrast from -1CV to +1CV:
Concept
This option provides four separate controls (all in stops):
DCcontrols the DC coefficient (block mean)LOW,MID,HIGHcontrol the AC coefficients in frequency order
All controls are interpreted as log2 gains (stops). For a value $x$, the gain is:
$$g(x) = 2^{x}$$
So +1 doubles, -1 halves.
DC
DC is scaled by:
$$g_\mathrm{DC} = 2^{DC}$$
and applied as:
$$DC' = \mathrm{clamp}(\mathrm{round}(g_\mathrm{DC} \cdot DC))$$
AC (low/mid/high weighting)
AC coefficients are processed in zigzag order (the JPEG natural order). Let $z$ be the AC position with $z = 1 \ldots A$, where $A$ is the number of AC coefficients.
Define a normalized position:
$$t = \begin{cases} \dfrac{z-1}{A-1} & A > 1 \\ 0 & A = 1 \end{cases}$$
Triangular weights:
- low weight fades out from low frequencies
$$w_\mathrm{low} = \max(0, 1 - 2t)$$
- mid weight peaks in the middle
$$w_\mathrm{mid} = 1 - |2t - 1|$$
- high weight fades in toward high frequencies
$$w_\mathrm{high} = \max(0, 2t - 1)$$
Per-coefficient exponent and gain:
$$v(z) = LOW\cdot w_\mathrm{low} + MID\cdot w_\mathrm{mid} + HIGH\cdot w_\mathrm{high}$$
$$g(z) = 2^{v(z)}$$
Applied to each AC coefficient:
$$AC'[z] = \mathrm{clamp}(\mathrm{round}(g(z)\cdot AC[z]))$$
If
DC = LOW = MID = HIGH = X, then all coefficients are scaled by the same gain $2^X$ (uniform contrast adjustment).Component Policy
Same as
-exposure-comp:- YCbCr/BG_YCC/YCCK: luma only
- RGB subtract-green: base/green only
- otherwise: all components
Ordering and Composition
Both
-exposure-compand-contrastare applied as a post step after any geometric transform (-rot,-flip,-crop, …). The tonal operations work on the final output coefficient arrays, so the order of switches on the command line does not matter.
Implementation notes
- Core implementation:
transupp.c:do_exposure_comp()anddo_contrast()transupp.h: adds new fields tojpeg_transform_info
- CLI parsing:
jpegtran.c
- Feature flags and parameters are stored in
jpeg_transform_infointransupp.h
Summary
-exposure-comp EVshifts brightness by changing only DC coefficients, with EV evaluated in linear light (sRGB transfer) at a log-average reference.-contrast DC LOW MID HIGHscales DC and AC coefficients, with AC gains varying smoothly over frequency order using low/mid/high controls.- Both run in the DCT domain and integrate naturally into the lossless-transformation workflow of
jpegtran.
Example pictures
-
Sommerzeit-EXIF automatisch korrigieren mit PowerShell
Ein häufiges Problem bei Digitalkameras: Die Sommerzeit ist noch in der Kamera aktiviert, obwohl bereits Winterzeit ist. Die Zeitstempel in den Fotos sind dadurch eine Stunde falsch und das fällt oft erst später auf, wenn man die Bilder sortiert oder mit anderen Fotos abgleicht.
Viele Kameras speichern die Sommerzeit-Einstellung in den EXIF-Daten. Bei Nikon-Kameras findet sich das "Daylight Savings"-Flag in den MakerNotes. Solange dieses auf "Yes" steht, sind die Zeitstempel um eine Stunde vorgestellt.
Das PowerShell-Script durchsucht alle Bilddateien (z.B. NEF bei Nikon), prüft ob das Sommerzeit-Flag noch aktiv ist, und korrigiert dann:
Die EXIF-Zeitstempel werden um 1 Stunde zurückgestellt Das Sommerzeit-Flag wird deaktiviert Die Windows-Datei-Zeitstempel (Erstellt/Geändert) werden angepasst.
Das Script nutzt das kostenlose Tool exiftool und zeigt für jede Datei übersichtlich an, was geändert wurde. Dateien mit bereits korrekter Zeit werden einfach übersprungen.Der exiftool-Pfad ist oben im Script konfigurierbar. Einfach das Script im Foto-Ordner ausführen. Unterordner werden automatisch durchsucht.
Das Ergebnis: Konsistente, korrekte Zeitstempel in allen Fotos, ohne manuelle Arbeit.
# PowerShell Script zur Korrektur der Sommerzeit in NEF-Dateien # Stellt die EXIF-Zeit um eine Stunde vor für Dateien, die Sommerzeit in Nikon MakerNotes haben # Testaufruf um DaylightSavings auszulesen: # C:\tools\exiftool -DaylightSavings DSC_1234.NEF # Daylight Savings : No # ===== KONFIGURATION ===== $exiftoolPath = "C:\tools\exiftool" # ========================= # Pfad zum aktuellen Verzeichnis $baseDir = $PSScriptRoot # Alle NEF-Dateien finden $nefFiles = Get-ChildItem -Path $baseDir -Recurse -Filter "*.NEF" Write-Host "Gefundene NEF-Dateien: $($nefFiles.Count)" -ForegroundColor Cyan $correctedCount = 0 $skippedCount = 0 foreach ($file in $nefFiles) { Write-Host "`nPrüfe: $($file.FullName)" -ForegroundColor Yellow try { # Lese Nikon Daylight Savings Flag aus MakerNotes $daylightSavings = & $exiftoolPath -s -s -s -DaylightSavings $file.FullName 2>&1 if ($LASTEXITCODE -ne 0) { Write-Host "⚠ Konnte MakerNotes nicht lesen" -ForegroundColor DarkYellow $skippedCount++ continue } Write-Host "Daylight Savings: $daylightSavings" -ForegroundColor Cyan # Prüfe, ob Sommerzeit aktiviert ist (Yes oder On) if ($daylightSavings -match "Yes|On") { Write-Host "→ Sommerzeit ist aktiviert - Korrektur erforderlich" -ForegroundColor Magenta # Zeige aktuelle Zeit $currentTime = & $exiftoolPath -s -s -s -DateTimeOriginal $file.FullName Write-Host "Aktuelle Zeit: $currentTime" -ForegroundColor White # Stellt die Zeit um 1 Stunde zurück (-1 Stunde) # -AllDates betrifft DateTimeOriginal, CreateDate und ModifyDate Write-Host "Stelle Zeit um 1 Stunde zurück und setze Sommerzeit zurück..." -ForegroundColor Magenta & $exiftoolPath -AllDates-=1:0:0 -DaylightSavings=No -overwrite_original $file.FullName 2>&1 | Out-Null if ($LASTEXITCODE -eq 0) { $newTime = & $exiftoolPath -s -s -s -DateTimeOriginal $file.FullName $newDST = & $exiftoolPath -s -s -s -DaylightSavings $file.FullName Write-Host "✓ Erfolgreich aktualisiert: $newTime" -ForegroundColor Green Write-Host " Sommerzeit jetzt: $newDST" -ForegroundColor Green # Setze Windows-Datei-Zeitstempel auf korrigierte EXIF-Zeit try { $exifDateTime = [DateTime]::ParseExact($newTime, "yyyy:MM:dd HH:mm:ss", $null) $file.CreationTime = $exifDateTime $file.LastWriteTime = $exifDateTime Write-Host " Datei-Zeitstempel aktualisiert" -ForegroundColor Green } catch { Write-Host " ⚠ Konnte Datei-Zeitstempel nicht setzen: $_" -ForegroundColor DarkYellow } $correctedCount++ } else { Write-Host "✗ Fehler beim Aktualisieren" -ForegroundColor Red } <# #> } else { Write-Host "→ Keine Sommerzeit - wird übersprungen" -ForegroundColor Gray $skippedCount++ } } catch { Write-Host "✗ Fehler: $_" -ForegroundColor Red Write-Host "Stelle sicher, dass exiftool installiert ist und im PATH verfügbar ist." -ForegroundColor Yellow break } } Write-Host "`n=== Fertig ===" -ForegroundColor Cyan Write-Host "Korrigierte Dateien: $correctedCount" -ForegroundColor Green Write-Host "Übersprungene Dateien: $skippedCount" -ForegroundColor Gray Write-Host "Gesamt geprüft: $($nefFiles.Count)" -ForegroundColor Cyan -
StickyMCP: Notes That Stick, Even in the Cloud
A MCP server is something an AI system can reach out to and actually do something with, unlike its usual diet of stale training data and existential boredom.
StickyMCP implements something refreshingly familiar: sticky notes. You type a short message, and it gets stored. Just like the real ones you stick on your coffee machine, desk surface, or whiteboard. Minimalism meets machine memory.
I built it during hackathon week, where ideas fly fast and only the sticky ones survive 🧷
Example: Using MCP Inspector to Display Text and Graph Output from the StickyMCP Server
🐙 GitHub Repository
Sticky code, sticky notes, find it all here:
https://github.com/jurgen178/mcp-sticky-notes
(or from my repo at https://github.com/microsoft/mcp-sticky-notes)🔧 What It Is
StickyMCP is a lightweight MCP server that lets users create, list, and delete virtual sticky notes, stored in Azure Table Storage and rendered either as plain text or classic sticky note-style PNGs. It showcases how the Model Context Protocol (MCP) can power distributed, developer-friendly microservices with visual flair.
StickyMCP provides a clean API for managing notes across systems, integrates naturally with Visual Studio Code Copilot Chat, and supports both HTTP and STDIO transports.
Each note is stored in Azure Table Storage (with in-memory fallback) and rendered as:
- Plain text (for automation and workflows)
- PNG images (for dashboards, markdown previews, or collaborative tools)
🧪 Core Features
- Add note
- List all notes
- Get note by ID
- Delete note by ID
- Delete all notes
- Group notes by logical key (e.g., personal, work, ideas)
- Render notes as PNGs
- Use in-memory fallback if Azure is unavailable
- HTTP or STDIO transport protocol
🖼️ Example Screenshots
Add a Sticky Note from a Client
Console Logging for Adding a Sticky Note
List all Sticky Notes from a Client

Console Logging for Listing All Sticky Notes
Short demo video showing how to add, list, and inspect sticky notes using MCP Inspector
🛠️ Tech Stack
- Server: MCP implementation in TypeScript
- Storage: Azure Table Storage (Managed Identity preferred)
- Rendering: PNG generation via node-canvas
📦 Installation
git clone https://github.com/jurgen178/mcp-sticky-notes
cd mcp-sticky-notes
npm install##### ☁️ Run on Azure Deploy server.ts as a WebApp on Azure. CoPilot can assist with setup, it is trained to handle this kind of deployment. Just ask.
##### 💻 Run Locally ```npx ts-node server.ts``` Server responds on ```http://localhost:3000``` Update your mcp.json: ``` { "servers": { "mcp-sticky-notes": { "url": "http://localhost:3000/mcp?userId=demo_user" } } } ```🧭 MCP Inspector
Use the MCP Inspector to debug
npx @modelcontextprotocol/inspectorSet command to
http://localhost:3000/mcp?userId=demo_user🌐 HTTP Endpoints
POST /mcp
GET /mcp
DELETE /mcpMCP clients must initialize first to receive a mcp-session-id.
🖼️ Client Limitation for Images
Not all clients can display the generated PNG images. For example, Visual Studio Code Copilot currently does not render them. Until image support is available, visual results can be viewed using the MCP Inspector.
📍 Why It Matters
StickyMCP demonstrates how MCP can be used to build scalable, visually engaging microservices that integrate seamlessly with Azure and developer tools.
-
C++ std::map using the __m128i type
In a recent project, I encountered a performance bottleneck while using std::map with CString as the key. The keys represented file extensions, each not exceeding seven Unicode characters. Given the performance-critical nature of the loop, the overhead of hashing CString for such short sequences was suboptimal.
To address this, I used the __m128i data type, which is part of the Streaming SIMD Extensions 2 (SSE2) in C++. This data type allows for handling 128-bit wide integer vectors, making it ideal for the file extensions mapping within the 128-bit limit.
To use the __m128i data type, custom hash and equality functions need to be defined for the map.
Using this data type significantly reduced the overhead and improved the performance of the map operations within the critical loop.
Custom hash and equality functions
// Custom hash function for __m128i. struct Hash128i { std::size_t operator()(const __m128i& key) const { const uint64_t* data = reinterpret_cast<const uint64_t*>(&key); return hash<uint64_t>{}(data[0]) ^ hash<uint64_t>{}(data[1]); } }; // Custom equality function for __m128i. struct Equal128i { bool operator()(const __m128i& lhs, const __m128i& rhs) const { // Compare the __m128i values using integer comparison. const __m128i result = _mm_cmpeq_epi32(lhs, rhs); // Check if all elements are equal. return _mm_movemask_epi8(result) == 0xFFFF; } };Declaration
unordered_map<__m128i, lpfnFormatGetInstanceProc, Hash128i, Equal128i> registered_format_plugins_map_m128;The project is using a function pointer as a data type, but it can be really anything.
typedef CPictureFormat* (__stdcall* lpfnFormatGetInstanceProc)();Map string to the __m128i data type
__m128i CRegisterFormat::str_to_m128i(const WCHAR* obj) { // Converts the first 8 characters of Unicode string obj into a __m128i. // Extension includes only a..z and 0..9, and 0..9 is case-insensitive, // and is at most 8 characters long. const size_t len = wcslen(obj); char pointy[16] = { 0 }; memcpy(pointy, obj, min(16, 2 * len)); // Initialize __m128i with the char array. const __m128i ext = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pointy)); // Case insensitve mapping. // The extension data is strictly A-Z0-9, so converting them to lowercase can be done by a vectorized operation bitwise OR with 0x20 (obj | 0x20). This moves A-Z to a-z while keeping 0-9, as this range already has this bit set. // Create a __m128i variable with all bytes set to 0x20. const static __m128i mask = _mm_set1_epi8(0x20); // Perform bitwise OR operation on all bytes. return _mm_or_si128(ext, mask); }Example usage
// Adding a new file extension with the associated function pointer for the file type. const __m128i key(str_to_m128i(ext)); if(registered_format_plugins_map_m128.find(key) == registered_format_plugins_map_m128.end()) { registered_format_plugins_map_m128[key] = fp; } // Implement the format factory. CPictureFormat* CRegisterFormat::GetInstance(const WCHAR* obj) { const WCHAR* ext(wcsrchr(obj, L'.')); auto fp = registered_format_plugins_map_m128[str_to_m128i(ext)]; if (fp) return fp(); return NULL; } // Compare two extensions to check if they share the same group defined by matching function pointer. bool CRegisterFormat::IsDifferentFormat(const WCHAR* obj1, const WCHAR* obj2) { // Get the file extensions. const WCHAR* ext1(wcsrchr(obj1, L'.')); const WCHAR* ext2(wcsrchr(obj2, L'.')); if ((ext1 == NULL) != (ext2 == NULL)) return true; return registered_format_plugins_map_m128[str_to_m128i(ext1)] != registered_format_plugins_map_m128[str_to_m128i(ext2)]; }
Seite 1 von 6
Ältere Beiträge →