MCP client for MWVM gateways. Interacts with Morpheum AI agent gateways via the Model Context Protocol (JSON-RPC 2.0 over HTTP).
Built with the same design principles as mwvm: thin facades, builder pattern, structured logging.
list— List all tools exposed by an MWVM gateway (name, description, input schema)call— Invoke a tool by name with JSON argumentsstatus— Show survival tier (credit-based compute), inspired by automaton- Survival-aware 402 handling — When payment required, shows tier context and payment details
- URL normalization — Accepts gateway URLs with or without trailing
/or/mcp - JSON validation — Validates tool call arguments before sending
- Structured logging — Uses
slogfor debug-level request logging - Builder API — Programmatic
ClientBuilderfor custom HTTP client, logger, base URL - Zero external CLI deps — Pure Go, no cobra/viper; minimal binary
go install github.com/fightclubx/mtool/cmd/mtool@latestOr build from source:
git clone https://github.com/fightclubx/mtool
cd mtool
go build -o mtool ./cmd/mtoolgo install github.com/fightclubx/mtool/cmd/mtool@latestYou need a running gateway to talk to. From the mwvm repo:
cd mwvm
cargo run -p mwvm-cli -- gateway --port 8080Or use any MWVM-compatible gateway URL (e.g. https://your-agent.example.com).
# List available tools
mtool list http://localhost:8080
# Call a tool
mtool call http://localhost:8080 infer '{"model_hash":"0","prompt_hash":"1"}'
# Check survival status (if gateway exposes /survival)
mtool status http://localhost:8080If the gateway is running, mtool list should show tools like infer and search_memory. If you see connection refused, start the gateway first.
| Command | Description |
|---|---|
mtool list <gateway-url> |
List available tools |
mtool call <gateway-url> <tool-name> [args-json] |
Call a tool with optional JSON args |
mtool status <gateway-url> |
Show survival tier (credit balance, tier) |
mtool help |
Show usage |
mtool version |
Show version (also -v, --version) |
# List tools from a local gateway
mtool list http://localhost:8080
# Call infer with required model_hash and prompt_hash
mtool call http://localhost:8080 infer '{"model_hash":"0","prompt_hash":"1"}'
# Call infer with max_tokens
mtool call http://localhost:8080 infer '{"model_hash":"0","prompt_hash":"1","max_tokens":256}'
# Call search_memory with query vector and k
mtool call http://localhost:8080 search_memory '{"query":[0.1,0.2,0.3],"k":5}'
# Call without args (uses empty object {})
mtool call http://localhost:8080 infer
# URL variants (all equivalent)
mtool list http://localhost:8080
mtool list http://localhost:8080/
mtool list http://localhost:8080/mcp
# Check survival status (credit-based compute)
mtool status http://localhost:8080Inspired by automaton: "If it cannot pay, it stops existing." Agents run on credit-based compute — no balance means no existence.
| Tier | Behavior |
|---|---|
| normal | Full capabilities. Frontier model inference. Fast heartbeat. |
| low_compute | Downgrades to cheaper model. Slows heartbeat. Sheds non-essential tasks. |
| critical | Minimal inference. Last-resort conservation. Seeking any path to revenue. |
| dead | Balance is zero. The agent stops. |
mtool status— QueriesGET /survivalfor tier, balance, and message. If the gateway does not expose this endpoint (404), returnsunknownwith guidance.- 402 Payment Required — When
listorcallreturns 402, mtool shows a survival-aware message with payment details (amount, currency, memo) and hints that the agent may be in critical/low_compute tier. - Gateway convention — Gateways may expose
GET /survivalreturning{ "tier": "normal", "balance": 123.45, "currency": "USDC", "message": "..." }.
When connected to an MWVM gateway, these tools are typically available:
| Tool | Description | Required Args | Optional Args |
|---|---|---|---|
infer |
Run inference on the agent's registered model | model_hash, prompt_hash |
max_tokens |
search_memory |
Vector search over the agent's persistent memory | query (array of numbers) |
k |
Use the client package for integration in Go applications:
package main
import (
"encoding/json"
"errors"
"fmt"
"log/slog"
"github.com/fightclubx/mtool/internal/client"
)
func main() {
c, err := client.NewBuilder().
BaseURL("http://localhost:8080").
Logger(slog.Default()).
Build()
if err != nil {
panic(err)
}
// List tools
tools, err := c.ListTools()
if err != nil {
panic(err)
}
for _, t := range tools {
fmt.Printf("%s: %s\n", t.Name, t.Description)
}
// Call a tool
args := json.RawMessage(`{"model_hash":"0","prompt_hash":"1"}`)
result, err := c.CallTool("infer", args)
if err != nil {
var paymentErr *client.ErrPaymentRequired
if errors.As(err, &paymentErr) {
// 402 — agent may be in critical/low_compute tier
fmt.Println("Payment required:", err)
return
}
panic(err)
}
fmt.Println(string(result))
// Survival status (if gateway exposes GET /survival)
status, _ := c.GetSurvivalStatus()
fmt.Printf("Tier: %s\n", status.Tier)
}| Method | Description |
|---|---|
BaseURL(url string) |
Gateway base URL (required) |
HTTPClient(c *http.Client) |
Custom HTTP client (default: http.DefaultClient) |
Logger(l *slog.Logger) |
Custom logger (default: slog.Default()) |
Build() |
Construct the Client (returns error if URL invalid) |
mtool speaks JSON-RPC 2.0 over HTTP:
| Method | Purpose |
|---|---|
tools/list |
Returns tool definitions (name, description, input_schema) |
tools/call |
Invokes a tool with name and arguments |
All requests are sent as POST /mcp to the gateway base URL with Content-Type: application/json.
{
"jsonrpc": "2.0",
"method": "tools/list",
"params": {},
"id": 1
}Success:
{
"jsonrpc": "2.0",
"result": { "tools": [...] },
"id": 1
}Error:
{
"jsonrpc": "2.0",
"error": { "code": -32601, "message": "method not found: ..." },
"id": 1
}Aligned with mwvm architecture:
| Pattern | Usage |
|---|---|
| Builder | ClientBuilder for configuration |
| Facade | Client — thin API over HTTP |
| Protocol | internal/protocol — MCP types (McpRequest, McpResponse, ToolDef, etc.) |
mtool/
├── cmd/mtool/main.go # CLI entry, commands: list, call, status
├── internal/
│ ├── client/
│ │ ├── client.go # ListTools, CallTool
│ │ ├── builder.go # ClientBuilder
│ │ └── survival.go # GetSurvivalStatus, ErrPaymentRequired
│ └── protocol/
│ ├── mcp.go # McpRequest, McpResponse, ToolDef
│ └── survival.go # Tier, SurvivalStatus, PaymentRequest
├── go.mod
└── README.md
- Go 1.22+
- A running MWVM gateway (e.g.
mwvm gateway --port 8080)
MIT