MCP Server Integration Guide

What is MCP

Model Context Protocol (MCP) is a standard for connecting AI agents to external tools and data sources. Instead of the agent making raw HTTP calls, it invokes named tools with structured parameters. The MCP server handles the implementation details.

Viatika's MCP server gives agents two tools:

  • pay_for_resource — make HTTP requests with automatic x402 payment handling
  • check_balance — check remaining credit balance

The agent never sees payment signatures, wallet addresses, or blockchain details. It just calls the tool and gets results.

Installation

Build from source

bash
cd ~/src/github.com/viatika-ai/platform
go build -o /usr/local/bin/viatika-mcp ./cmd/agent-mcp

Verify installation

bash
viatika-mcp --help
# or just verify it exists:
which viatika-mcp

Configuration

The MCP server reads configuration from environment variables:

VariableRequiredDefaultDescription
VIATIKA_API_URLyeshttp://localhost:8081Viatika platform API base URL
VIATIKA_API_TOKENyesAPI token (format: vt_live_...)
VIATIKA_ORG_IDyesOrganization UUID
VIATIKA_ENTITY_IDyesEntity UUID (user or swarm)
LOG_LEVELnoinfoLog verbosity: debug or info

Setup: Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or equivalent:

json
{
  "mcpServers": {
    "viatika": {
      "command": "/usr/local/bin/viatika-mcp",
      "env": {
        "VIATIKA_API_URL": "https://api.viatika.ai",
        "VIATIKA_API_TOKEN": "vt_live_abc123456789...",
        "VIATIKA_ORG_ID": "550e8400-e29b-41d4-a716-446655440000",
        "VIATIKA_ENTITY_ID": "660e8400-e29b-41d4-a716-446655440001"
      }
    }
  }
}

Restart Claude Desktop. The tools appear in the tool picker (hammer icon).

Setup: Other MCP-Compatible Agents

Any agent supporting MCP stdio transport can use the server. The key configuration:

  • Transport: stdio (stdin/stdout JSON-RPC)
  • Command: /usr/local/bin/viatika-mcp
  • Environment: set the 4 required variables

The server identifies itself as "Viatika x402 Payment Agent" version "1.0.0".


Tool Reference

pay_for_resource

Make an HTTP request to a URL. If the response is 402 Payment Required, automatically sign the payment through Viatika and retry with payment headers.

Parameters

ParameterTypeRequiredDefaultDescription
urlstringyesThe URL to request
methodstringno"GET"HTTP method: GET, POST, PUT, DELETE, etc.
headersobjectno{}HTTP headers as key-value pairs
bodystringno""Request body (for POST/PUT)

Return Value

json
{
  "success": true,
  "status_code": 200,
  "body": "response body content",
  "headers": {
    "Content-Type": "application/json"
  },
  "payment_made": true,
  "amount_usdc": "1.50"
}
FieldTypeDescription
successbooleantrue if final status code is 2xx
status_codeintegerHTTP status code of final response
bodystringResponse body
headersobjectResponse headers
payment_madebooleantrue if a 402 was encountered and payment was signed
amount_usdcstringUSDC amount paid (only if payment_made is true)
errorstringError message (only on failure)

Flow

  1. Makes the HTTP request to url with specified method, headers, and body
  2. If response is not 402 → returns the response directly
  3. If response is 402:
    1. Extracts x402 payload from response body or Payment-Required header
    2. Sends payload to Viatika /v1/x402/sign-payment for policy check + signing
    3. If denied → returns error with denial reason
    4. If approved → retries original request with X-Payment and X-Payment-Signature headers
    5. Returns final response with payment_made: true

Example Usage in Conversation

User: “Fetch the weather data from https://weather-api.example.com/forecast”

Agent calls pay_for_resource:

json
{
  "url": "https://weather-api.example.com/forecast",
  "method": "GET"
}

Tool returns:

json
{
  "success": true,
  "status_code": 200,
  "body": "{\"forecast\": \"sunny, 24°C\"}",
  "payment_made": true,
  "amount_usdc": "0.05"
}

Agent: “The forecast is sunny at 24°C. (This required a $0.05 payment which was automatically processed.)”


check_balance

Check the current credit balance for the configured entity.

Parameters

None.

Return Value

json
{
  "organization_id": "550e8400-e29b-41d4-a716-446655440000",
  "entity_id": "660e8400-e29b-41d4-a716-446655440001",
  "balance_credits": 8500,
  "balance_usd": "$8.50",
  "note": "You have 8500 credits available (1 credit = $0.001)"
}
FieldTypeDescription
organization_idstringOrganization UUID
entity_idstringEntity UUID
balance_creditsintegerBalance in credits
balance_usdstringBalance formatted as USD
notestringHuman-readable summary

Example Usage in Conversation

User: “How much budget do I have left?”

Agent calls check_balance (no arguments).

Tool returns:

json
{
  "organization_id": "550e8400-...",
  "entity_id": "660e8400-...",
  "balance_credits": 8500,
  "balance_usd": "$8.50",
  "note": "You have 8500 credits available (1 credit = $0.001)"
}

Agent: “You have $8.50 (8,500 credits) remaining.”


Example Conversation Flow

Here's a complete interaction showing how an agent uses both tools:

User: Check my balance, then fetch the premium dataset from
      https://data-api.example.com/v2/market-analysis

Agent: Let me check your balance first.
[calls check_balance]
→ You have 15,000 credits ($15.00)

Agent: You have $15.00 available. Now let me fetch that dataset.
[calls pay_for_resource with url="https://data-api.example.com/v2/market-analysis"]
→ {success: true, payment_made: true, amount_usdc: "2.00", body: "..."}

Agent: Got it! The request cost $2.00 in x402 micropayments. You now have
approximately $13.00 remaining. Here's the market analysis data: ...

Error Scenarios

Payment denied

json
{
  "success": false,
  "status_code": 402,
  "payment_made": false,
  "error": "Payment signing denied: Daily budget of 5000 credits exceeded"
}

The agent should report the denial reason and suggest the user check their budget settings.

No x402 payload in 402

json
{
  "success": false,
  "status_code": 402,
  "payment_made": false,
  "error": "no x402 payload found in response"
}

The service returned 402 but didn't include valid x402 payment information.

Network error to Viatika

json
{
  "success": false,
  "status_code": 402,
  "payment_made": false,
  "error": "Payment signing failed: send request: dial tcp: connection refused"
}

The agent should report a connectivity issue with the payment service.

Troubleshooting

MCP server doesn't start

Check stderr output (MCP uses stdout for JSON-RPC, logs go to stderr):

bash
VIATIKA_API_URL=https://api.viatika.ai \
VIATIKA_API_TOKEN=vt_live_... \
VIATIKA_ORG_ID=your-org-uuid \
VIATIKA_ENTITY_ID=your-entity-uuid \
viatika-mcp 2>/tmp/viatika-mcp.log

Check /tmp/viatika-mcp.log for errors. Common issues:

  • Missing environment variables → "VIATIKA_API_TOKEN is required"
  • Binary not found → check path in config
  • Permission denied → chmod +x /usr/local/bin/viatika-mcp

Tools don't appear in Claude Desktop

  1. Check the config JSON is valid (no trailing commas, correct quotes)
  2. Restart Claude Desktop completely (quit and reopen)
  3. Look for error banners in the Claude Desktop UI
  4. Try running the binary manually to verify it works

Payment always denied

  1. Check balance: call check_balance to verify credits exist
  2. Check token scopes: ensure token has x402:sign and credits:consume
  3. Check budget policies: the entity may have exhausted their budget period
  4. Check provider whitelist: the target service may not be whitelisted

Timeout errors

The MCP server has a 30-second HTTP timeout. If the target service or Viatika API is slow:

  • Check network connectivity
  • The target URL may be unreachable
  • Viatika API may be under load (signing takes ~150ms normally)