Metadata-Version: 2.4
Name: mcpiko
Version: 0.1.0
Summary: MCP client library for Python — like paramiko, but for MCP servers
Project-URL: Homepage, https://github.com/traxiom/mcpiko
Project-URL: Repository, https://github.com/traxiom/mcpiko
Project-URL: Issues, https://github.com/traxiom/mcpiko/issues
Author-email: Traxiom <muratazimli@gmail.com>
License: MIT
Keywords: agent,ai,devops,mcp,model-context-protocol,server,ssh
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.11
Requires-Dist: requests>=2.31
Provides-Extra: dev
Requires-Dist: black; extra == 'dev'
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Provides-Extra: ssh
Requires-Dist: paramiko>=3.0; extra == 'ssh'
Description-Content-Type: text/markdown

# mcpiko

**MCP client library for Python — like paramiko, but for MCP servers.**

Connect to any [Model Context Protocol](https://modelcontextprotocol.io) server and call its tools as native Python methods. No boilerplate, no JSON-RPC plumbing.

```python
from mcpiko import MCPClient

client = MCPClient("http://server:9765", api_key="secret")

print(client.tools())
# ['server_status', 'get_logs', 'active_devices', 'risk_snapshot', ...]

print(client.server_status())
# === CONTAINERS ===
# hos_web   Up 3 hours (healthy)   0.0.0.0:80->8000/tcp
# hos_redis Up 3 hours (healthy)   127.0.0.1:6379->6379/tcp
# ...

print(client.active_devices())
# DEVICE        ST        BALANCE       EQUITY     MARGIN LICENSE
# ────────────────────────────────────────────────────────────────
# 5f3d88f149…   🟢    $ 100001.76 $ 100001.76 $     0.00 ACTIVE
```

## Why

[paramiko](https://www.paramiko.org/) lets you SSH into a server and run commands. `mcpiko` lets you connect to an **MCP server** and call **structured tools** — with proper argument types, auto-generated Python methods, and clean error handling.

```
paramiko:  SSH → raw shell commands
mcpiko:    MCP → typed tool calls → Python methods
```

## Install

```bash
pip install mcpiko          # HTTP transport (default)
pip install mcpiko[ssh]     # + SSH transport (paramiko)
```

## Connection modes

### HTTP (remote server with exposed port)

```python
from mcpiko import MCPClient

with MCPClient("http://server:9765", api_key="your-key") as client:
    print(client.risk_snapshot())
    print(client.get_logs(source="app", lines=100))
```

### SSH (no port needed — runs script on remote host)

```python
client = MCPClient.from_ssh(
    "root@135.181.25.224",
    key_file="~/.ssh/id_ed25519",
    script="/opt/app/deploy/mcp_server.py",
)
print(client.active_devices())
client.close()
```

### Environment variables

```bash
export MCPIKO_SSH_HOST=135.181.25.224
export MCPIKO_SSH_KEY=~/.ssh/id_ed25519
export MCPIKO_SCRIPT=/opt/app/deploy/mcp_server.py
```

```python
client = MCPClient.from_env()
```

## CLI

```bash
# List tools
mcpiko http://server:9765 --key SECRET tools

# Call a tool
mcpiko http://server:9765 --key SECRET call server_status
mcpiko http://server:9765 --key SECRET call get_logs --source app --lines 50

# Via SSH
mcpiko root@server --ssh-key ~/.ssh/id_ed25519 call active_devices
```

## Tool discovery

```python
client = MCPClient("http://server:9765", api_key="...")

# All available tools
print(client.tools())

# Tool signature
print(client.tool_info("get_logs"))
# {'name': 'get_logs', 'description': '...', 'inputSchema': {...}}

# Call by name (dynamic)
result = client.call("get_logs", source="app", lines=50)
```

## Error handling

```python
from mcpiko import MCPClient, MCPAuthError, MCPToolError, MCPConnectionError

try:
    client = MCPClient("http://server:9765", api_key="wrong-key")
except MCPAuthError:
    print("Bad API key")

try:
    result = client.call("unknown_tool")
except MCPToolError as e:
    print(f"Tool failed: {e}")
```

## Roadmap

- [x] v0.1.0 — HTTP transport, auto-discovery, dynamic methods, SSH transport, CLI
- [ ] v0.2.0 — Persistent SSH session, async client (`AsyncMCPClient`), streaming
- [ ] v0.3.0 — Tool schema validation, retry logic, connection pooling
- [ ] v1.0.0 — Stable API, full test suite, type stubs

## License

MIT
