server-dev

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ContextVM Server Development

ContextVM 服务器开发

Build MCP servers that expose capabilities over Nostr using the
@contextvm/sdk
.
使用
@contextvm/sdk
构建可在Nostr网络上暴露功能的MCP服务器。

Quick Start

快速开始

Create a basic ContextVM server:
typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { NostrServerTransport } from "@contextvm/sdk";
import { PrivateKeySigner } from "@contextvm/sdk";
import { ApplesauceRelayPool } from "@contextvm/sdk";

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

const server = new McpServer({
  name: "my-server",
  version: "1.0.0",
});

// Register tools
server.registerTool(
  "echo",
  { description: "Echo back the input" },
  async ({ message }) => ({
    content: [{ type: "text", text: `Echo: ${message}` }],
  }),
);

const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  serverInfo: {
    name: "My ContextVM Server",
    website: "https://example.com",
  },
});

await server.connect(transport);
console.log("Server running on Nostr");
创建基础ContextVM服务器:
typescript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { NostrServerTransport } from "@contextvm/sdk";
import { PrivateKeySigner } from "@contextvm/sdk";
import { ApplesauceRelayPool } from "@contextvm/sdk";

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

const server = new McpServer({
  name: "my-server",
  version: "1.0.0",
});

// 注册工具
server.registerTool(
  "echo",
  { description: "Echo back the input" },
  async ({ message }) => ({
    content: [{ type: "text", text: `Echo: ${message}` }],
  }),
);

const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  serverInfo: {
    name: "My ContextVM Server",
    website: "https://example.com",
  },
});

await server.connect(transport);
console.log("Server running on Nostr");

NostrServerTransport Options

NostrServerTransport 选项

OptionTypeDescription
signer
NostrSigner
Required. Signs all Nostr events
relayHandler
RelayHandler | string[]
Required. Relay connection manager.
serverInfo
ServerInfo
Optional. Metadata for announcements
isPublicServer
boolean
Publish server announcements. Default:
false
allowedPublicKeys
string[]
Whitelist client public keys
excludedCapabilities
CapabilityExclusion[]
Bypass whitelist for specific methods
injectClientPubkey
boolean
Inject client pubkey into
_meta
. Default:
false
encryptionMode
EncryptionMode
OPTIONAL
,
REQUIRED
, or
DISABLED
选项类型描述
signer
NostrSigner
必填项。对所有Nostr事件进行签名
relayHandler
RelayHandler | string[]
必填项。中继连接管理器。
serverInfo
ServerInfo
可选项。公告用元数据
isPublicServer
boolean
发布服务器公告。默认值:
false
allowedPublicKeys
string[]
客户端公钥白名单
excludedCapabilities
CapabilityExclusion[]
针对特定方法绕过白名单
injectClientPubkey
boolean
将客户端公钥注入
_meta
。默认值:
false
encryptionMode
EncryptionMode
OPTIONAL
REQUIRED
DISABLED

Access Control

访问控制

Public Key Whitelisting

公钥白名单

Restrict which clients can connect:
typescript
const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  allowedPublicKeys: ["client1-pubkey-hex", "client2-pubkey-hex"],
});
限制可连接的客户端:
typescript
const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  allowedPublicKeys: ["client1-pubkey-hex", "client2-pubkey-hex"],
});

Capability Exclusions

功能排除

Allow specific operations from any client:
typescript
const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  allowedPublicKeys: ["trusted-client"],
  excludedCapabilities: [
    { method: "tools/list" }, // Anyone can list tools
    { method: "tools/call", name: "public_tool" }, // Specific tool is public
  ],
});
允许任意客户端执行特定操作:
typescript
const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  allowedPublicKeys: ["trusted-client"],
  excludedCapabilities: [
    { method: "tools/list" }, // 任何人都可列出工具
    { method: "tools/call", name: "public_tool" }, // 特定工具为公开
  ],
});

Public Server Announcements

公共服务器公告

Enable discovery by publishing replaceable events:
typescript
const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  isPublicServer: true,
  serverInfo: {
    name: "Weather Service",
    about: "Get weather data worldwide",
    website: "https://weather.example.com",
  },
});
Publishes events on kinds 11316-11320 with your server's capabilities.
通过发布可替换事件启用发现功能:
typescript
const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  isPublicServer: true,
  serverInfo: {
    name: "Weather Service",
    about: "Get weather data worldwide",
    website: "https://weather.example.com",
  },
});
会发布类型为11316-11320的事件,包含服务器的功能信息。

Client Public Key Injection

客户端公钥注入

Access the client's identity in your tools:
typescript
const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  injectClientPubkey: true,
});

// In your tool handler, access _meta.clientPubkey
server.registerTool("personalized", {...}, async (args, extra) => {
  const clientPubkey = extra._meta?.clientPubkey;
  // Use pubkey for personalization, rate limiting, etc.
});
在工具中访问客户端身份:
typescript
const transport = new NostrServerTransport({
  signer,
  relayHandler: relayPool,
  injectClientPubkey: true,
});

// 在工具处理器中,访问_meta.clientPubkey
server.registerTool("personalized", {...}, async (args, extra) => {
  const clientPubkey = extra._meta?.clientPubkey;
  // 使用公钥进行个性化处理、速率限制等操作
});

Server Templates

服务器模板

See
assets/server-template.ts
for a complete starting point.
完整的起点模板请查看
assets/server-template.ts

Debugging (MCP Inspector)

调试(MCP 检查器)

Use the MCP Inspector to validate your MCP server behavior (tools/resources/prompts schemas, request/response shape) before exposing it via ContextVM.
From the MCP docs, the Inspector is typically run via
npx
:
bash
npx @modelcontextprotocol/inspector <command>
Practical workflow for ContextVM:
  1. Implement and test your server logic using a standard MCP transport (commonly STDIO) so it can be inspected.
  2. Use the Inspector to iterate on tool schemas and error handling.
  3. Once stable, swap the transport to
    NostrServerTransport
    .
If you need details on Inspector usage and common debugging steps, read:
  • references/debugging-inspector.md
在通过ContextVM暴露MCP服务器之前,可使用MCP检查器验证服务器行为(工具/资源/提示的 schema、请求/响应格式)。
根据MCP文档,检查器通常通过
npx
运行:
bash
npx @modelcontextprotocol/inspector <command>
ContextVM的实用工作流:
  1. 使用标准MCP传输(通常为STDIO)实现并测试服务器逻辑,以便进行检查。
  2. 使用检查器迭代优化工具schema和错误处理。
  3. 稳定后,将传输切换为
    NostrServerTransport
如需了解检查器的使用细节和常见调试步骤,请阅读:
  • references/debugging-inspector.md

Reference Materials

参考资料

  • references/transport-config.md
    - All configuration options
  • references/security-patterns.md
    - Access control patterns
  • references/gateway-pattern.md
    - Exposing existing servers
  • references/transport-config.md
    - 所有配置选项
  • references/security-patterns.md
    - 访问控制模式
  • references/gateway-pattern.md
    - 暴露现有服务器