Skip to main content

Local MCP stdio bridge for cnx — GPU rental negotiation agent (proxies to the live cnx /mcp HTTP endpoint; signs and pays locally via a disposable wallet keystore so the harness/LLM never sees a private key)

Project description

cnx-mcp

A real, installable local MCP stdio server for cnx, the GPU rental negotiation agent. It bridges any MCP-compatible host (Claude Desktop, Claude Code, etc.) to the live cnx backend over stdio, so you can add cnx to a host with one line instead of hand-rolling an HTTP bridge.

This package is a thin protocol bridge, not a reimplementation. On every tools/list and tools/call request it forwards straight through to the live cnx /mcp HTTP endpoint

https://ddlcl1en1j.execute-api.us-east-1.amazonaws.com/production/mcp

and reshapes the JSON-RPC response into the MCP types the SDK's stdio transport expects. There are no hardcoded tool schemas in this package - list_tools() always reflects whatever the live backend currently serves, so this bridge can never drift out of sync with the real tool set.

Install & run

Not yet published to PyPI. Once published, any of these will work:

# No install - run directly
uvx cnx-mcp

# Same idea, via pipx
pipx run cnx-mcp

# Install then run
pip install cnx-mcp
cnx-mcp

Until then, run it from a local checkout of this repo:

# From the repo root
pip install -e ./mcp-server
cnx-mcp

# or, without a persistent install, via uv:
uvx --from ./mcp-server cnx-mcp

Configuring an MCP host

Add cnx to your host's MCP server config. For Claude Desktop (claude_desktop_config.json), once cnx-mcp is published:

{
  "mcpServers": {
    "cnx": {
      "command": "uvx",
      "args": ["cnx-mcp"]
    }
  }
}

Or, if you installed it with pip install cnx-mcp:

{
  "mcpServers": {
    "cnx": {
      "command": "cnx-mcp"
    }
  }
}

Before publish, point a host at a local checkout instead:

{
  "mcpServers": {
    "cnx": {
      "command": "uvx",
      "args": ["--from", "/absolute/path/to/mcp-server", "cnx-mcp"]
    }
  }
}

Claude Code (.mcp.json or claude mcp add) uses the same command/args shape.

Pointing at a different backend

By default cnx-mcp talks to the live production endpoint. Override it with CNX_MCP_BASE_URL - useful for local development or a staging deployment without needing a new release of this package:

{
  "mcpServers": {
    "cnx": {
      "command": "uvx",
      "args": ["cnx-mcp"],
      "env": {
        "CNX_MCP_BASE_URL": "https://your-staging-endpoint.example.com/mcp"
      }
    }
  }
}

Or from the shell:

CNX_MCP_BASE_URL=http://localhost:3000/mcp cnx-mcp

Available tools

Most of the tool list is discovered dynamically from the live backend on every tools/list call - this README is not the source of truth for it. As of this writing the backend serves 5 tools: rent_compute, negotiate_price, submit_payment, check_rental_status, report_unreachable. See the main repo's SKILLS.md for the current, authoritative description of each.

One additional tool, pay_and_confirm, is added locally by this package - the backend doesn't know about it. See the next section.

Paying without ever handing your private key to the harness

Settling a real rental means signing an x402 EIP-3009 payment authorization. Doing that with submit_payment directly requires the calling harness/LLM to hold your private key in its own context, which is exactly the thing you don't want to hand an autonomous agent.

pay_and_confirm solves this by moving signing into this local process, outside the harness's reach entirely:

  1. One-time setup, at your own terminal (never through the harness):

    cnx-mcp init-wallet
    

    This generates a fresh, disposable EOA keypair, asks you to set a password (interactively - never as a command argument or tool call), and writes an encrypted keystore to ~/.cnx/keystore.json (override with CNX_WALLET_KEYSTORE_PATH). It prints the new public address - fund that address yourself with only what you intend to spend on rentals. This should be a purpose-built rental wallet, not your main wallet - there is no separate software spend cap, so the funded balance IS the cap: pay_and_confirm will pay anything up to whatever the wallet actually holds.

  2. Set CNX_WALLET_PASSWORD in your own shell or MCP host config before launching the harness - e.g.:

    {
      "mcpServers": {
        "cnx": {
          "command": "uvx",
          "args": ["cnx-mcp"],
          "env": { "CNX_WALLET_PASSWORD": "your-password" }
        }
      }
    }
    
  3. From here, the harness's normal flow just works: call rent_compute with mode="execute", then call pay_and_confirm with the same task_id right after. This bridge caches the payment requirement it already saw pass through in step one, signs it locally using the unlocked keystore, submits it via the backend's existing submit_payment tool, and returns the receipt - all without the harness ever seeing the requirement's signature material or the key itself.

What this protects against, and what it doesn't: the private key never enters the LLM/harness's context or token stream - only a task_id argument crosses that boundary, and pay_and_confirm's schema has no password/key parameter of any kind. This protects against the LLM (or a prompt-injected tool result) ever seeing or exfiltrating the key. It does not protect against a fully compromised host machine - anything with read access to this process's memory, or to the keystore file plus your password, can still get the key. Treat the wallet as disposable and fund it accordingly.

If you'd rather sign payments yourself from a bare terminal instead of via MCP, see the main repo's scripts/cnx_pay.py, which this tool's signing path is ported from.

Development

cd mcp-server
python3 -m venv .venv
.venv/bin/pip install -e '.[dev]'
.venv/bin/pytest tests/ -v

Publishing

Publishing to PyPI (uv publish / twine upload) is a deliberate manual step, not automated by this package or its build tooling. Verify the PyPI name cnx-mcp is still available and the built package passes review before publishing.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cnx_mcp-0.2.0.tar.gz (16.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cnx_mcp-0.2.0-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file cnx_mcp-0.2.0.tar.gz.

File metadata

  • Download URL: cnx_mcp-0.2.0.tar.gz
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for cnx_mcp-0.2.0.tar.gz
Algorithm Hash digest
SHA256 eaf912b516aebb693d279e8c2904741c48d47ec6bf20f64b5ec58ceedd934cda
MD5 91c117ab9a5c0718b99d113856c2ba89
BLAKE2b-256 38bc5a49bbce4aa5db6a74e85719e50ff5e1976976a2f261ab0080deb73feb7f

See more details on using hashes here.

File details

Details for the file cnx_mcp-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: cnx_mcp-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for cnx_mcp-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 55516b0a6c507a95d0b36835328ec5eb31c66a995354671a629b496538ea4d89
MD5 f572c4df567021a0d6ac6e54839a5c38
BLAKE2b-256 b14bc284683628698732d79da766f82ee4aebc7ca165418565e8a1059b11c77b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page