Skip to content
quick start

Custom agent

If you're building your own agent, you don't need a host. Spawn argand-mcp directly and speak MCP stdio (JSON-RPC over newline-delimited frames on stdin/stdout).

1. Install argand-mcp

cargo install --git ssh://git@git.argand.org/nicweyand/argand.git argand-mcp

2. Wire shape (raw frames)

The MCP spec is JSON-RPC 2.0 over stdio with one frame per line. Stdout is reserved for protocol; logs go to stderr.

→ stdin (initialize) json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-agent","version":"0.1.0"}}}
→ stdin (tools/list) json
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
→ stdin (tools/call → search) json
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"search","arguments":{"query":"rust async runtime","num_results":5}}}

3. Minimal Python driver

Roughly 30 lines of stdlib. No MCP SDK required — but if you want one, the official mcp Python package on Forgejo mirrors the same protocol.

agent.py python
import json
import subprocess

proc = subprocess.Popen(
    ["argand-mcp"],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True,
    bufsize=1,
)

def rpc(method: str, params: dict | None = None, id_: int = 0) -> dict:
    frame = {"jsonrpc": "2.0", "id": id_, "method": method}
    if params is not None:
        frame["params"] = params
    proc.stdin.write(json.dumps(frame) + "\n")
    proc.stdin.flush()
    return json.loads(proc.stdout.readline())

# 1) Handshake.
rpc("initialize", {
    "protocolVersion": "2025-03-26",
    "capabilities": {},
    "clientInfo": {"name": "my-agent", "version": "0.1.0"},
}, id_=1)

# 2) List tools.
print(rpc("tools/list", id_=2))

# 3) Search.
print(rpc("tools/call", {
    "name": "search",
    "arguments": {"query": "rust async runtime", "num_results": 5},
}, id_=3))

For production: handle notifications/cancelled, the response envelope's isError flag, and the content[].type === "text" wrapper. The MCP stdio reference page covers the full envelope.

Don't want a subprocess?

Hit Argand's REST API directly — same backend, no MCP layer. See the REST reference or grab one of the SDKs. Self-hosters running argand themselves can also speak the public gRPC surface on port :50100.