ctxcn is a command-line utility inspired by shadcn that streamlines the integration of ContextVM (CVM) servers into your TypeScript projects. It generates a type-safe client from a CVM server's tool definitions, allowing you to call CVM tools as if they were native TypeScript functions.
-
Install dependencies
npm install @contextvm/sdk # or bun add @contextvm/sdk -
Initialize your project
npx @contextvm/ctxcn init
-
Add a CVM server client
npx @contextvm/ctxcn add <pubkey>
npm install -g @contextvm/ctxcnnpm install --save-dev @contextvm/ctxcngit clone https://github.com/your-username/ctxcn.git
cd ctxcn
bun installThe ctxcn utility provides four main commands: init, add, update, and help.
Initialize your project with a ctxcn.config.json file:
npx @contextvm/ctxcn initThis will start an interactive process to configure your project settings.
Generate a TypeScript client from a CVM server's tool definitions:
npx @contextvm/ctxcn add <pubkey>This will:
- Connect to the specified CVM server
- Display server information and available tools
- Allow you to customize the client name
- Provide options to:
- Generate and save the client file
- Print the generated code to console only
- Cancel the operation
Refresh existing CVM server clients with the latest tool definitions:
# Update a specific client
npx @contextvm/ctxcn update <pubkey>
# Update all clients or select from a list
npx @contextvm/ctxcn updateDisplay help information:
npx @contextvm/ctxcn helpThe ctxcn utility can be configured via a ctxcn.config.json file in your project's root directory:
source: The source directory for the generated client.relays: An array of relays to use when connecting to CVM servers.privateKey: The private key to use when connecting to CVM servers. This will be used as a fallback if theCTXCN_PRIVATE_KEYenvironment variable is not set.addedClients: An array of public keys of the clients that have been added. This is automatically managed by the CLI.
For better security, you can use environment variables instead of storing private keys in your configuration file:
# Set your private key as an environment variable
export CTXCN_PRIVATE_KEY="your-private-key-here"The CLI sets the ContextVM SDK logger to a minimal level by default to reduce noisy output during operations (for example when running src/commands/add.ts). By default the CLI will set LOG_LEVEL=error unless you explicitly provide a different value.
You can override the logging behavior with the following environment variables supported by the SDK:
LOG_LEVEL— Minimum log level:debug,info,warn,error. Default used by the CLI:error.LOG_DESTINATION— Destination for logs:stderr(default),stdout, orfile.LOG_FILE— Path to the log file whenLOG_DESTINATION=file.LOG_ENABLED— Enable or disable logging:true(default) orfalse.
Examples:
# Run the add command with verbose debug logs
LOG_LEVEL=debug npx @contextvm/ctxcn add <pubkey>
# Log to a file instead of the console
LOG_DESTINATION=file LOG_FILE=./app.log npx @contextvm/ctxcn add <pubkey>
# Disable SDK logging entirely
LOG_ENABLED=false npx @contextvm/ctxcn add <pubkey>The generated clients use the following order of precedence for private keys:
- Private key passed directly in the constructor options
CTXCN_PRIVATE_KEYenvironment variable- Private key from the configuration file (as a fallback)
Here is an example of how to use the generated client:
The generated client exports a singleton instance for convenience. The instance is named using camelCase of the server name to avoid collisions:
import { addition } from "./src/ctxcn/AdditionClient.ts";
// The singleton uses the default configuration
const result = await addition.add(5, 10);
console.log(result.result); // 15
await addition.disconnect();You can also create your own instance with custom configuration:
import { AdditionClient } from "./src/ctxcn/AdditionClient.ts";
// The client will automatically use the CTXCN_PRIVATE_KEY environment variable
// or the private key from the configuration file
const mcpClient = new AdditionClient();
const result = await mcpClient.add(5, 10);
console.log(result.result); // 15
await mcpClient.disconnect();You can override the private key and relays when creating a client instance:
import { AdditionClient } from "./src/ctxcn/AdditionClient.ts";
const mcpClient = new AdditionClient({
privateKey: "your-custom-private-key",
relays: ["wss://your-custom-relay.org"],
});
const result = await mcpClient.add(5, 10);
console.log(result.result); // 15
await mcpClient.disconnect();