AgentSkillsCN

client-dev

构建能够通过 Nostr 连接至 ContextVM 服务器的 MCP 客户端。适用于创建客户端、发现服务器、连接远程服务器、处理加密连接,或为现有 MCP 客户端实现代理模式时使用。

SKILL.md
--- frontmatter
name: client-dev
description: Build MCP clients that connect to ContextVM servers over Nostr. Use when creating clients, discovering servers, connecting to remote servers, handling encrypted connections, or implementing the proxy pattern for existing MCP clients.

ContextVM Client Development

Build MCP clients that connect to ContextVM servers over the Nostr network.

Quick Start

Connect to a ContextVM server:

typescript
import { Client } from '@modelcontextprotocol/sdk/client';
import {
	NostrClientTransport,
	PrivateKeySigner,
	ApplesauceRelayPool,
	EncryptionMode
} from '@contextvm/sdk';

const signer = new PrivateKeySigner(process.env.CLIENT_PRIVATE_KEY!);
const relayPool = new ApplesauceRelayPool(['wss://relay.contextvm.org', 'wss://cvm.otherstuff.ai']);

const SERVER_PUBKEY = 'server-public-key-hex';

const transport = new NostrClientTransport({
	signer,
	relayHandler: relayPool,
	serverPubkey: SERVER_PUBKEY,
	encryptionMode: EncryptionMode.OPTIONAL
});

const client = new Client({
	name: 'my-client',
	version: '1.0.0'
});

await client.connect(transport);

// Use the client
const tools = await client.listTools();
const result = await client.callTool({
	name: 'echo',
	arguments: { message: 'Hello' }
});

Server Discovery

Direct Connection (Known Pubkey)

Connect when you know the server's public key:

typescript
const transport = new NostrClientTransport({
	signer,
	relayHandler: relayPool,
	serverPubkey: 'known-server-pubkey'
});

Discovery via Announcements

Find servers broadcasting on the network:

typescript
import { CTXVM_MESSAGES_KIND, SERVER_ANNOUNCEMENT_KIND } from '@contextvm/sdk';

// Query relays for server announcements
await relayPool.subscribe([{ kinds: [SERVER_ANNOUNCEMENT_KIND] }], (event) => {
	const serverInfo = JSON.parse(event.content);
	console.log(`Found server: ${serverInfo.serverInfo.name}`);
	console.log(`Pubkey: ${event.pubkey}`);
});

NostrClientTransport Options

OptionTypeDescription
signerNostrSignerRequired. Signs all Nostr events
relayHandlerRelayHandler | string[]Required. Relay connection manager
serverPubkeystringRequired. Target server's public key
encryptionModeEncryptionModeOPTIONAL, REQUIRED, or DISABLED
isStatelessbooleanSkip initialization handshake. Default: false
logLevelLogLevelLogging verbosity

Stateless Mode

Skip the initialization handshake for faster connections:

typescript
const transport = new NostrClientTransport({
	signer,
	relayHandler: relayPool,
	serverPubkey: SERVER_PUBKEY,
	isStateless: true // Skip initialize roundtrip
});

Proxy Pattern

Use NostrMCPProxy to connect existing MCP clients to ContextVM servers:

typescript
import { NostrMCPProxy } from '@contextvm/sdk';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const proxy = new NostrMCPProxy({
	// Local transport for existing client to connect to
	mcpHostTransport: new StdioServerTransport(),

	// Remote server connection
	nostrTransportOptions: {
		signer,
		relayHandler: relayPool,
		serverPubkey: SERVER_PUBKEY
	}
});

await proxy.start();

This allows any standard MCP client to use ContextVM servers without native support.

Encryption

Control encryption behavior:

typescript
// Require encrypted connections only
encryptionMode: EncryptionMode.REQUIRED;

// Use encryption if server supports it (default)
encryptionMode: EncryptionMode.OPTIONAL;

// Never use encryption
encryptionMode: EncryptionMode.DISABLED;

Client Templates

See assets/client-template.ts for a complete boilerplate.

Tooling: ctxcn (generate a typed TypeScript client)

If you are building a TypeScript app and want remote ContextVM tools to feel like local functions, use ctxcn.

High-level behavior:

  • Connects to a ContextVM server.
  • Reads tools/list schemas.
  • Generates TypeScript client code into your repo (shadcn-style: you own the generated code).

From ContextVM docs/blog references, the basic flow is:

bash
npx @contextvm/ctxcn init
npx @contextvm/ctxcn add <server-pubkey>
npx @contextvm/ctxcn update

Use this when:

  • You want end-to-end type safety.
  • You want IDE autocomplete for server tools.
  • You want to avoid hand-writing tool interfaces.

Reference Materials