Skip to content

feat(cli): pakx install end-to-end for MCP servers#1

Merged
arwenizEr merged 1 commit into
mainfrom
feat/install-mcp
May 21, 2026
Merged

feat(cli): pakx install end-to-end for MCP servers#1
arwenizEr merged 1 commit into
mainfrom
feat/install-mcp

Conversation

@arwenizEr
Copy link
Copy Markdown
Collaborator

Summary

Implements Step 8 of the master prompt: real pakx install loop for MCP server dependencies.

  • pakx-core: expand McpServer payload with version + McpTransport enum (Stdio { command, args, env } / Http { url, headers }). Add lockfile_key(), computed_integrity(), short_name().
  • pakx-agents (Claude Code): new project_root field + with_project_root builder; install_mcp writes to <project_root>/.mcp.json with read-modify-write merge that preserves unrelated server entries. uninstall falls back to MCP entry removal when no skill dir matches.
  • pakx: new install module with two sub-modules:
    • mcp_translate: turn an official-MCP Package's install_hints into a concrete McpTransport — supports npm (npx -y), pypi (uvx), docker/oci (docker run), and remote HTTP/SSE.
    • runner: read manifest → fan out via RegistryClient → translate → install via adapter → aggregate into agents.lock. Failures collected per-dep so partial installs still produce a lockfile + summary.
  • CLI: pakx install [-C dir] [--no-lockfile] [--mcp-base-url URL] [--claude-home DIR]. Last two flags hidden, for testing.

Skills / subagents / prompts / commands / hooks are listed as "skipped (not yet supported)" until Step 9 wires their sources + adapters.

Test plan

  • cargo fmt --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • 6 new mcp_translate unit tests
  • 6 new claude_code_mcp integration tests
  • 5 new end-to-end pakx install tests with wiremock + temp project root
  • CI test matrix (ubuntu / macos / windows) green

Workspace test count rises to ~108.

🤖 Generated with Claude Code

- Expand pakx-core::install::McpServer with version + McpTransport
  enum (Stdio/Http). Add lockfile_key, computed_integrity, short_name.
- ClaudeCodeAdapter: project_root field + with_project_root builder,
  install_mcp writes to <project_root>/.mcp.json with read-modify-write
  merge that preserves unrelated server entries. uninstall falls back
  to MCP entry strip when no skill dir matches.
- pakx-agents pulls in serde + serde_json for .mcp.json schema.
- New pakx::install module: mcp_translate (Package install_hints →
  McpTransport; supports npm/pypi/docker stdio + remote http) +
  runner (resolve via RegistryClient → translate → install → write
  agents.lock). Failures collected per-dep so partial installs still
  emit a lockfile and human-readable summary.
- pakx install CLI: --directory, --no-lockfile, --mcp-base-url (hidden,
  testing), --claude-home (hidden, testing).
- Tests: 6 mcp_translate unit, 6 claude_code_mcp integration, 5
  install end-to-end with wiremock. Updates claude_code.rs test that
  asserted install_mcp was Unsupported.

Workspace test count ~108. Skills/subagents/prompts/commands/hooks
listed as 'skipped' until Step 9 wires their sources + adapters.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@arwenizEr arwenizEr merged commit e123a87 into main May 21, 2026
2 of 5 checks passed
@arwenizEr arwenizEr deleted the feat/install-mcp branch May 21, 2026 12:27
arwenizEr added a commit that referenced this pull request May 21, 2026
Same-named query against two different registry deployments was
mapping to the same on-disk cache file, returning the stale earlier
response. Reproduced on ubuntu CI in the federated search test:
test #1 cached `acme/one`+`acme/two` for the OfficialMcpSource at
mock-url-A; test #2 set up mock-url-B serving different content, but
the empty-query cache key `official-mcp:search:` collided and the
later test read the earlier mock's body.

Cache key is now `{tag}@{base_url}:search:{query}` (and equivalent
for fetch). Different registries can no longer collide.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
arwenizEr added a commit that referenced this pull request May 21, 2026
* feat(registry-client): add Smithery source (search-only at v0.1)

- SmitherySource against registry.smithery.ai (configurable base URL,
  TTL-cached like OfficialMcpSource). Returns Package rows from
  /servers with qualifiedName as canonical id, displayName as name,
  description, and full extra JSON in install_hints.
- fetch() returns NotFound at v0.1 since Smithery's connection /
  config schema differs from the official MCP Registry's packages[]
  shape; install via Smithery lands in Phase A v2 once the
  translator grows a Smithery codepath.
- pakx search now defaults to fanning out to both OfficialMcp +
  Smithery (parallel via RegistryClient::search). Flags:
  --smithery-base-url URL (hidden, testing); --no-smithery (opt out).
- 5 new wiremock-backed source tests + 1 new end-to-end federated
  search test covering both sources.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(registry-client): include base URL in cache key

Same-named query against two different registry deployments was
mapping to the same on-disk cache file, returning the stale earlier
response. Reproduced on ubuntu CI in the federated search test:
test #1 cached `acme/one`+`acme/two` for the OfficialMcpSource at
mock-url-A; test #2 set up mock-url-B serving different content, but
the empty-query cache key `official-mcp:search:` collided and the
later test read the earlier mock's body.

Cache key is now `{tag}@{base_url}:search:{query}` (and equivalent
for fetch). Different registries can no longer collide.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant