@stellar-mcp/client SDK
v0.2.0 — Type-safe programmatic client for Stellar MCP servers — discover tools, call Soroban contracts, simulate transactions with fee estimates, and sign/submit with pluggable signer adapters.
Overview
@stellar-mcp/client is the SDK layer for interacting with MCP servers generated by stellar mcp generate. It speaks the MCP JSON-RPC 2.0 protocol over HTTP and exposes a clean TypeScript API for:
- Tool discovery — list all tools a server exposes and their schemas
- Contract calls — invoke any server tool and receive typed results (including XDR for write operations)
- Transaction signing — pluggable signer adapters for secret keys, Freighter browser wallets, and PasskeyKit smart wallets
- Transaction confirmation — poll the Stellar RPC until a transaction finalises
Installation
npm install @stellar-mcp/clientPeer Dependencies
| Package | Required | Use case |
|---|---|---|
@modelcontextprotocol/sdk | Yes | MCP transport layer |
@stellar/stellar-sdk | Yes | XDR signing, RPC calls |
@creit.tech/stellar-wallets-kit | Optional | Freighter browser signer |
passkey-kit | Optional | PasskeyKit smart wallet signer |
# Minimal (Node.js / server-side)
npm install @modelcontextprotocol/sdk @stellar/stellar-sdk
# With browser wallet support
npm install @creit.tech/stellar-wallets-kit
# With PasskeyKit smart wallet support
npm install passkey-kitQuick Start — Type-Safe (Recommended)
Generate a typed client file from your running MCP server:
npx mcp-generate-types --url http://localhost:3001/mcp --out ./src/mcp-types.tsThe generated types reflect your contract’s functions — tool names, arg shapes, and result types are all derived from whatever contract you passed to stellar mcp generate.
import { createMCPClient } from './src/mcp-types'; // generated — reflects your contract
import { secretKeySigner } from '@stellar-mcp/client';
import { Networks } from '@stellar/stellar-sdk';
const client = createMCPClient({
url: 'http://localhost:3001/mcp',
networkPassphrase: Networks.TESTNET,
rpcUrl: 'https://soroban-testnet.stellar.org',
});
const { data: admin } = await client.call('get-admin');
const { data: count } = await client.call('get-token-count');
const { xdr } = await client.call('deploy-token', {
deployer: 'GABC...',
config: { name: 'MyToken', symbol: 'MTK', decimals: 7 },
});
const result = await client.signAndSubmit(xdr!, {
signer: secretKeySigner(process.env.SECRET_KEY!),
});
console.log(result.hash, result.status); // → 'SUCCESS'
client.close();Quick Start — Untyped
Use MCPClient directly without code generation. Tool names and args are string / unknown.
import { MCPClient, secretKeySigner } from '@stellar-mcp/client';
import { Networks } from '@stellar/stellar-sdk';
const client = new MCPClient({
url: 'http://localhost:3001/mcp',
networkPassphrase: Networks.TESTNET,
rpcUrl: 'https://soroban-testnet.stellar.org',
});
const tools = await client.listTools();
console.log(tools.map(t => t.name));
const { data: admin } = await client.call('get-admin');
const { xdr } = await client.call('deploy-token', {
deployer: 'GABC...',
config: { /* ... */ },
});
const result = await client.signAndSubmit(xdr!, {
signer: secretKeySigner(process.env.SECRET_KEY!),
});
client.close();Simulate Before You Sign
client.simulate() gives you a fee preview and dry-run result before asking the user to sign — ideal for showing “This will cost ~0.0001 XLM” or warning if a transaction will fail.
import { MCPClient, secretKeySigner } from '@stellar-mcp/client';
import { Networks } from '@stellar/stellar-sdk';
const client = new MCPClient({
url: 'http://localhost:3001/mcp',
networkPassphrase: Networks.TESTNET,
rpcUrl: 'https://soroban-testnet.stellar.org',
});
// 1. Preview — no signing, no fees
const preview = await client.simulate('deploy-token', {
deployer: 'GABC...',
config: { name: 'MyToken', symbol: 'MTK', decimals: 7 },
});
console.log(`Estimated fee: ${preview.fee} stroops`);
// e.g. "1000 stroops" → 0.0001 XLM
// 2. Only proceed if user confirms
const { hash } = await client.signAndSubmit(preview.xdr!, {
signer: secretKeySigner(process.env.SECRET_KEY!),
});
// 3. Wait for finality
const result = await client.waitForConfirmation(hash);
console.log(result.status); // → 'SUCCESS'
client.close();simulate() returns { xdr, fee, simulationResult }:
xdr— assembled transaction XDR, ready to pass tosignAndSubmit()fee— estimated fee in stroops (divide by 10,000,000 for XLM)simulationResult— for read-only tools, this is the answer (no XDR or fee)
The Smart Wallet template uses this automatically — users see the estimated fee in the confirmation modal before signing.
mcp-generate-types CLI
Connects to a live MCP server and generates a typed TypeScript file with per-tool arg and result interfaces.
# Generate types from a running server
npx mcp-generate-types --url http://localhost:3001/mcp
# Custom output path
npx mcp-generate-types --url http://localhost:3001/mcp --out ./src/mcp-types.ts| Flag | Default | Description |
|---|---|---|
--url | required | MCP server URL |
--out | mcp-types.ts | Output file path |
Regenerate whenever the contract changes — the generated file reflects the live server’s tool list.
The CLI emits one arg interface + one result interface per tool, plus a createMCPClient factory:
// Auto-generated by @stellar-mcp/client — DO NOT EDIT
import { MCPClient, type MCPClientOptions, type ToolMap } from '@stellar-mcp/client';
export interface DeployTokenArgs {
deployer: string;
config: {
admin: string;
name: string;
symbol: string;
decimals: number;
token_type: { tag: 'Allowlist' } | { tag: 'Pausable' } | { tag: 'Capped' };
};
}
export type GetAdminArgs = Record<string, never>;
export interface DeployTokenResult {
xdr: string;
simulationResult?: unknown;
}
interface ServerTools extends ToolMap {
'get-admin': { args: GetAdminArgs; result: { xdr: string } };
'deploy-token': { args: DeployTokenArgs; result: DeployTokenResult };
}
export function createMCPClient(options: MCPClientOptions): MCPClient<ServerTools> {
return new MCPClient<ServerTools>(options);
}Schema Utilities
Helper functions for building UIs on top of MCP tool definitions. These work on the JSON Schema from ToolInfo.inputSchema — useful for Telegram bots, React forms, CLIs, or any custom interface.
import {
extractArgs,
buildToolArgs,
parseArgValue,
isReadOperation,
type ArgDef,
} from '@stellar-mcp/client';extractArgs(tool)
Flattens a tool’s inputSchema into a sorted, display-ready ArgDef[]. Handles nested objects, discriminated unions ({ tag: "Value" } pattern), nullable types, and enum fields. Required args come before optional.
const args = extractArgs(tool);
// [{ name: 'deployer', path: ['deployer'], type: 'string', required: true }, ...]buildToolArgs(args, collected)
Reconstructs the nested args object from a flat key→value map, ready to pass to client.call().
const toolArgs = buildToolArgs(args, {
deployer: 'GABC...',
'config.admin': 'GDEF...',
'config.decimals': 7,
});
// { deployer: 'GABC...', config: { admin: 'GDEF...', decimals: 7 } }parseArgValue(value, arg)
Coerces a user-typed string into the correct JS type for the given ArgDef.
parseArgValue('42', { type: 'number', ... }) // → 42
parseArgValue('true', { type: 'boolean', ... }) // → true
parseArgValue('', { type: 'string', nullable: true, ... }) // → nullisReadOperation(toolName)
Returns true for tool names starting with read-only prefixes (get, list, query, fetch, find, search, is, has, check, count).
isReadOperation('get-admin') // true
isReadOperation('deploy-token') // falseFor the full API reference including all signers, error types, transport details, and logging, see API Reference.