Skip to content

Generalize npx providers to support any stdio MCP subprocess#1

Merged
BillJr99 merged 2 commits into
mainfrom
claude/hermes-mcp-servers-cDR8B
May 25, 2026
Merged

Generalize npx providers to support any stdio MCP subprocess#1
BillJr99 merged 2 commits into
mainfrom
claude/hermes-mcp-servers-cDR8B

Conversation

@BillJr99

Copy link
Copy Markdown
Owner

Summary

Refactors the MCP provider system to support any stdio-based MCP server subprocess—not just npx commands. This includes support for uvx, python -m, installed binaries, and any other command that speaks the MCP stdio transport. Adds support for pip requirements and setup commands that run on every server startup.

Key Changes

  • Renamed npx_runner.pyprocess_runner.py: Generalized the subprocess spawning and session management to handle any command, not just npx. The NpxSession class is now ProcessSession with a backward-compatible alias.

  • Updated YAML schema:

    • Changed npx: key to package: (legacy npx: still accepted for backward compatibility)
    • Added requirements: list for pip packages to install before server startup
    • Added setup_commands: list for shell commands to run on every server startup
  • Frontend API changes:

    • Renamed /api/introspect-npx/api/introspect (accepts command, requirements, setup_commands)
    • Removed /api/run-command endpoint (setup commands now declarative in YAML)
    • Updated provider type from "npx" to "package" in structured JSON
    • Changed field npx_commandcommand in provider objects
  • Package manager detection: Added _detect_package_manager() helper to identify the package manager from command prefix (npx, uvx, python, npm) for logging/display purposes.

  • Server-side setup: Added run_provider_setup() function that:

    • Installs pip requirements via subprocess.run([sys.executable, "-m", "pip", "install", ...])
    • Runs setup commands via subprocess.run(shlex.split(cmd))
    • Executes before the provider is registered
  • UI updates:

    • Wizard now accepts any command (with examples: npx, uvx, python -m, installed binary)
    • Added editable lists for requirements and setup commands in both wizard and editor
    • Removed "Run Command" modal (replaced by declarative setup commands)
    • Updated badges and labels from "npx" to "package"
  • Validation: Updated _validate_provider() to check requirements and setup_commands are lists if present.

  • Tests: Added comprehensive test coverage for:

    • Package provider YAML round-tripping
    • Requirements and setup commands persistence
    • Introspection with requirements/setup commands
    • Package manager detection
    • Removal of old endpoints

Implementation Details

  • The ProcessSession class maintains one persistent connection per command string, reusing it across tool calls for efficiency.
  • Introspection spawns a fresh temporary session (not reusing the persistent one) to avoid side effects.
  • Setup commands and requirements are installed fresh on every server startup (not cached), ensuring consistency across restarts.
  • The subprocess is started lazily on first tool call, not at server startup, so setup commands run just-in-time.

https://claude.ai/code/session_016EMphWWMguzwVrfAYvJFSX

claude added 2 commits May 25, 2026 02:20
…p_commands

- Rename npx_runner.py → process_runner.py; class NpxSession → ProcessSession
  (NpxSession alias kept for backward compat)
- Add SUBPROCESS_KEYS = ('package', 'npx') so existing npx: YAML files keep
  working unchanged; saving through the UI rewrites them to package: format
- Add _get_package_command() helper that checks both keys in priority order
- Add run_provider_setup() that pip-installs requirements and runs setup_commands
  on every server startup (safe no-op when already installed)
- Add requirements: and setup_commands: fields to both code and package providers
  in YAML, structured JSON, validation, and editor UI
- Merge all introspect endpoints into a single POST /api/introspect that accepts
  command + requirements + setup_commands; removes /api/introspect-npx
- Remove the ad-hoc 'Run Command' modal; setup_commands replace it persistently
- Simplify the wizard to 2 cards: Python Code and Package
- Package card accepts any command (npx, uvx, python -m, installed binary);
  package manager auto-detected from the command prefix for display purposes
- Update provider list badges: 'pkg' (purple) for package, 'code' (blue) for code
- Add provider_type field to GET /api/tools list; is_npx kept as backward-compat alias
- Install uv via pip in Dockerfile so uvx-based providers work out of the box;
  add /root/.local/bin to PATH
- Add pip install uv step to GitHub Actions CI workflow
- 150/150 tests pass covering all new behavior and backward compat

https://claude.ai/code/session_016EMphWWMguzwVrfAYvJFSX
- SUBPROCESS_KEYS reduced to ('package',); npx: key no longer read
- _get_package_command() simplified to a direct spec.get('package') lookup
- _get_package_spec() in frontend/app.py simplified to spec.get('package')
- Removed is_npx alias from GET /api/tools list response
- Removed is_npx || is_package JS fallback in provider list rendering
- Removed all backward-compat test cases for npx: key
- Updated SUBPROCESS_KEYS test to assert ('package',) exactly
- Removed backward-compat notes from README
- 144/144 tests pass

https://claude.ai/code/session_016EMphWWMguzwVrfAYvJFSX
@BillJr99 BillJr99 merged commit a851c0f into main May 25, 2026
2 checks passed
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.

2 participants