This guide will help you get up and running with Poly MCP in minutes.
If you haven't already, install Poly MCP:
cargo install poly-mcp
See the Installation guide for other installation methods.
Poly MCP communicates via stdin/stdout using JSON-RPC 2.0:
poly-mcp
The server is now running and waiting for commands.
In another terminal, send an initialization message:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | poly-mcp
You should receive a response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "1.0.0",
"serverInfo": {
"name": "poly-mcp",
"version": "0.1.0"
},
"capabilities": {
"tools": {}
}
}
}
See all available tools:
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | poly-mcp
Example - Read a file:
echo '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "fs_read",
"arguments": {
"path": "/etc/hosts"
}
}
}' | poly-mcp
For interactive exploration, use a JSON-RPC client:
const { spawn } = require('child_process');
const mcp = spawn('poly-mcp');
// Send a request
const request = {
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: {
name: "fs_read",
arguments: { path: "/etc/hosts" }
}
};
mcp.stdin.write(JSON.stringify(request) + '\n');
// Handle response
mcp.stdout.on('data', (data) => {
console.log('Response:', JSON.parse(data.toString()));
});
import subprocess
import json
# Start the server
process = subprocess.Popen(
['poly-mcp'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True
)
# Send a request
request = {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "fs_read",
"arguments": {"path": "/etc/hosts"}
}
}
process.stdin.write(json.dumps(request) + '\n')
process.stdin.flush()
# Read response
response = json.loads(process.stdout.readline())
print(response)
Read a file:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "fs_read",
"arguments": {"path": "./README.md"}
}
}
Write to a file:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "fs_write",
"arguments": {
"path": "./output.txt",
"content": "Hello, World!"
}
}
}
Read specific line ranges:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "fs_read",
"arguments": {
"path": "./large_file.log",
"lines": [[1, 10], [100, 120]]
}
}
}
Replace specific lines in a file:
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "fs_write",
"arguments": {
"path": "./config.txt",
"content": "# Updated config\nversion=2.0",
"lines": [[1, 2]]
}
}
}
Create a snapshot:
{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "fs_snapshot",
"arguments": {
"path": "./project",
"max_snapshots": 5
}
}
}
Check repository status:
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "git_status",
"arguments": {"path": "."}
}
}
View commit history:
{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "git_log",
"arguments": {
"path": ".",
"limit": 10
}
}
}
Run diagnostics on a project:
{
"jsonrpc": "2.0",
"id": 6,
"method": "tools/call",
"params": {
"name": "diagnostics_get",
"arguments": {"path": "./src"}
}
}
Fetch a URL as Markdown:
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "net_fetch",
"arguments": {
"url": "https://example.com",
"convert_to_markdown": true
}
}
}
Query package information:
{
"jsonrpc": "2.0",
"id": 8,
"method": "tools/call",
"params": {
"name": "net_cargo",
"arguments": {
"crate_name": "tokio",
"action": "latest"
}
}
}
Example integration with an MCP client:
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
// Create transport
const transport = new StdioClientTransport({
command: 'poly-mcp',
args: []
});
// Create client
const client = new Client({
name: 'my-app',
version: '1.0.0'
}, {
capabilities: {}
});
// Connect
await client.connect(transport);
// Call a tool
const result = await client.callTool({
name: 'fs_read',
arguments: { path: '/etc/hosts' }
});
console.log(result);
Create a helper script for easier usage:
#!/bin/bash
# poly-mcp-call.sh - Helper for calling Poly MCP tools
TOOL=$1
ARGS=$2
REQUEST=$(cat <<EOF
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "$TOOL",
"arguments": $ARGS
}
}
EOF
)
echo "$REQUEST" | poly-mcp
Usage:
./poly-mcp-call.sh fs_read '{"path":"/etc/hosts"}'
Set up environment variables for customization:
# Set log level
export POLY_MCP_LOG_LEVEL=debug
# Configure snapshot defaults
export POLY_MCP_MAX_SNAPSHOTS=10
# Set script timeout
export POLY_MCP_TIMEOUT=300
# Start server with config
poly-mcp
All errors follow the JSON-RPC 2.0 error format:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32000,
"message": "File not found",
"data": {
"path": "/nonexistent/file.txt"
}
}
}
Common error codes:
-32700 - Parse error-32600 - Invalid request-32601 - Method not found-32602 - Invalid params-32603 - Internal error-32000 to -32099 - Server-defined errorsStart every session with an initialize call:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
Check for the error field in responses:
const response = JSON.parse(output);
if (response.error) {
console.error('Error:', response.error.message);
process.exit(1);
}
Increment request IDs for easier debugging:
let id = 1;
function makeRequest(method, params) {
return {
jsonrpc: "2.0",
id: id++,
method,
params
};
}
Always use absolute paths or validate relative paths:
const path = require('path');
const absolutePath = path.resolve(relativePath);
For long-running operations, set appropriate timeouts:
{
"name": "silent_script",
"arguments": {
"script": "#!/bin/bash\\nsleep 10",
"timeout": 15
}
}
export POLY_MCP_LOG_LEVEL=debug
poly-mcp
Log all requests and responses:
poly-mcp 2>&1 | tee poly-mcp.log
Use jq to validate and format JSON:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | \
jq '.' | \
poly-mcp | \
jq '.'
Now that you're familiar with the basics: