The inputSchema `type: "number"` is advisory only — runtime may receive a
string payload that gets interpolated into the osascript template. Coerce
tab_id via Number.parseInt before interpolating at all four sites.
Affected sites:
- findTabById(tabId)
- executeTabOperation(tabId, ...) (close_tab, switch_to_tab, reload_tab,
go_back, go_forward)
- execute_javascript handler
- get_page_content handler
The shared toSafeTabId() helper returns null for missing values (preserving
the active-tab fallthrough) and throws on non-numeric input (surfacing misuse
via the existing request-level try/catch, consistent with the missing-code
path in execute_javascript).
Align with other examples — no example ships a Dockerfile or its own
.gitignore. Rust build artifacts are now covered by the repo-level
.gitignore instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
First example of the binary server type — a compiled Rust MCP server
packaged as an MCPB. Based on the official Rust SDK calculator example
(rmcp 1.2.0, 2 tools: sum/sub, ~80 LOC).
Includes Cargo.toml, Dockerfile for Docker-based builds, .mcpbignore
to exclude source from the bundle, and README with build/pack/test
instructions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- hello-world-node: wrap server startup in async main() with proper
await on server.connect(transport) — fixes crash on initialize in
Claude Desktop UtilityProcess runtime (closes#200)
- hello-world-uv: add required mcp_config block — v0.4 schema requires
it but the example omitted it, causing mcpb pack to fail
- file-manager-python: convert from broken v0.1/python to v0.4/uv —
the old manifest had privacy_policies on v0.1 (schema violation),
used command "python" (ENOENT on macOS), and had no bundled deps.
Now uses UV runtime with proper mcp_config (closes#47, closes#72)
- Graduate UV runtime from experimental across docs and schema comments
- Bump DEFAULT_MANIFEST_VERSION from 0.2 to 0.3
All three examples verified: pack succeeds, server responds to MCP
initialize over stdio, tools/list returns expected tools.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add UV as a new server type for Python extensions that use UV runtime
for dependency management instead of bundling dependencies.
Schema changes (v0.4):
- Add "uv" to server.type enum
- Make mcp_config optional (not needed for UV type)
- UV extensions rely on pyproject.toml for dependencies
Documentation:
- Add UV runtime section to MANIFEST.md explaining benefits and usage
- Update README.md to recommend UV runtime for Python
- Add complete hello-world-uv example
Benefits of UV runtime:
- Cross-platform support (Windows/macOS/Linux, Intel/ARM)
- Small bundle size (~100 KB vs 5-10 MB)
- Handles compiled dependencies portably
- No user Python installation required
Example manifest:
{
"manifest_version": "0.4",
"server": {
"type": "uv",
"entry_point": "src/server.py"
}
}
Co-authored-by: Joan <joan@anthropic.com>
Implements icon validation to catch common issues that prevent icons from
displaying in Claude Desktop. Uses a non-blocking warning approach for
remote URLs to maintain flexibility for MCPB's evolving multi-platform
ecosystem.
## Changes
### Core Implementation (src/node/validate.ts)
- Add `isPNG()` helper to validate PNG file signatures via magic bytes
- Add `validateIcon()` function with comprehensive checks:
- **Warn** about remote URLs (non-blocking, best practice guidance)
- **Reject** ${__dirname} variable usage in icon field (doesn't work)
- **Reject** absolute paths (not portable)
- Verify icon file exists at specified path
- Verify icon file is valid PNG format
- Recommend 512×512 size for Claude Desktop
- Integrate icon validation into `validateManifest()` after schema validation
### Test Coverage
- Update `test/icon-validation.test.ts` - Remote URL test now expects warning
- Update `test/cli.test.ts` - Integration test updated for warnings
- All 109 tests passing
### Documentation Updates
- Update examples/hello-world-node/manifest.json to v0.3
## Validation Behavior
**Remote URLs (WARNING - non-blocking):**
```
Icon path uses a remote URL. Best practice for local MCP servers:
Use local files like "icon": "icon.png" for maximum compatibility.
Claude Desktop currently only supports local icon files in bundles.
```
**Result:** Validation passes, developer is informed
**Other Issues (ERROR - blocking):**
- ${__dirname} usage: Rejects (doesn't work)
- Absolute paths: Rejects (not portable)
- Missing files: Rejects (broken reference)
- Non-PNG files: Rejects (wrong format)
## Rationale
**Non-Blocking Approach:**
- Doesn't prevent valid bundles from being created
- Educates developers about best practices
- Maintains flexibility as MCPB evolves beyond Claude Desktop
- Future-proof if remote URL support is added
**Still Protective:**
- Blocks truly broken configurations (missing files, wrong formats)
- Provides actionable error messages for fixable issues
Based on real-world findings from investigating icon display issues in
Claude Desktop with production MCPB bundles.
Add optional privacy_policies array field to manifest.json that allows
developers to declare their data handling practices. This field accepts
an array of privacy policy statements that describe how the extension
collects, uses, and protects user data.
- Update manifest schema to include privacy_policies field
- Add empty privacy_policies array to all example manifests
- Document the new field in MANIFEST.md
- Replace manifest_version with $schema field pointing to official schema URL
- Support backward compatibility with legacy dxt_version field
- Update all examples and tests to use new $schema field
- Mark dxt_version as deprecated but still functional
- Require either $schema or dxt_version (at least one must be present)