contextvm-sdk 0.1.1

Rust SDK for the ContextVM protocol — MCP over Nostr
Documentation
---
title: Common Tool Schemas
description: Compute and publish CEP-15 common tool schema hashes with the @contextvm/sdk.
---

# Common Tool Schemas

The `@contextvm/sdk` includes helpers for [CEP-15](/spec/ceps/cep-15) common tool schemas.

For most server integrations, prefer `withCommonToolSchemas()`. It decorates `NostrServerTransport` and publishes the required metadata automatically.

Use the lower-level utilities on this page when you need to precompute hashes, verify compatibility, or assert schema stability in tests or other scenarios.

## Recommended usage

The usual integration point is `withCommonToolSchemas()`:

```typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import {
  NostrServerTransport,
  PrivateKeySigner,
  withCommonToolSchemas,
} from '@contextvm/sdk';

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

server.registerTool(
  'translate_text',
  {
    description: 'Translate text between languages.',
    inputSchema: {
      type: 'object',
      properties: {
        text: { type: 'string' },
        target_language: { type: 'string' },
      },
      required: ['text', 'target_language'],
    },
    outputSchema: {
      type: 'object',
      properties: {
        translated_text: { type: 'string' },
      },
      required: ['translated_text'],
    },
  },
  async ({ text, target_language }) => ({
    content: [{ type: 'text', text: `Translated to ${target_language}: ${text}` }],
    structuredContent: {
      translated_text: `Translated to ${target_language}: ${text}`,
    },
  }),
);

const transport = withCommonToolSchemas(
  new NostrServerTransport({
    signer: new PrivateKeySigner('your-server-private-key'),
    relayHandler: ['wss://relay.damus.io'],
    isAnnouncedServer: true,
  }),
  {
    tools: [{ name: 'translate_text' }],
  },
);

await server.connect(transport);
```

This is the recommended path because the SDK will automatically:

- compute the CEP-15 schema hash;
- inject `_meta['io.contextvm/common-schema'].schemaHash` into `tools/list` results;
- add matching `i` and `k` tags to announced tools lists.

For more transport-specific context, see [Nostr Server Transport](/ts-sdk/transports/nostr-server-transport#cep-15-common-tool-schemas).

## Exports

The SDK exports:

- `computeCommonSchemaHash()`
- `normalizeSchema()`
- `COMMON_SCHEMA_META_NAMESPACE`

## Schema normalization

`normalizeSchema()` removes documentation-only fields that do not participate in CEP-15 schema identity.

This includes:

- `title`
- `description`
- `examples`
- `default`
- `deprecated`
- `readOnly`
- `writeOnly`
- vendor extension keys starting with `x-`

The resulting normalized schema is then suitable for deterministic hashing.

## Computing a schema hash

```typescript
import { computeCommonSchemaHash } from '@contextvm/sdk';

const schemaHash = computeCommonSchemaHash({
  name: 'translate_text',
  inputSchema: {
    type: 'object',
    properties: {
      text: { type: 'string', description: 'Input text' },
      target_language: { type: 'string', title: 'Target language' },
    },
    required: ['text', 'target_language'],
  },
  outputSchema: {
    type: 'object',
    properties: {
      translated_text: { type: 'string' },
    },
    required: ['translated_text'],
  },
});
```

The hash is computed from:

- the tool `name`;
- the normalized `inputSchema`;
- the normalized `outputSchema`, when present.

## Manual verification

If you need to verify a schema hash yourself, compute it from the tool definition and compare it against `_meta['io.contextvm/common-schema'].schemaHash`.

```typescript
import {
  COMMON_SCHEMA_META_NAMESPACE,
  computeCommonSchemaHash,
} from '@contextvm/sdk';
import type { Tool } from '@modelcontextprotocol/sdk/types.js';

function hasMatchingSchemaHash(tool: Tool): boolean {
  const expectedHash = computeCommonSchemaHash({
    name: tool.name,
    inputSchema: tool.inputSchema,
    outputSchema: tool.outputSchema,
  });

  return (
    tool._meta?.[COMMON_SCHEMA_META_NAMESPACE]?.schemaHash === expectedHash
  );
}
```

This is mainly useful for tests, debugging, and custom verification flows.

## Constraints

- Tool `name` is part of the hash.
- `outputSchema` affects the hash when present.
- Schemas must be self-contained before hashing.
- Remote `$ref` values are not supported during hash computation and must be resolved in advance.

## Next Steps

For the recommended server-side integration, see [Nostr Server Transport](/ts-sdk/transports/nostr-server-transport#cep-15-common-tool-schemas).