Skip to main content

Getting Started

This guide walks you through setting up a CTP tool development environment.

Prerequisites

  • Node.js 18+ or 20+
  • npm, pnpm, or yarn
  • TypeScript 5.0+

Project Setup

1. Create a New Project

mkdir my-ctp-tools
cd my-ctp-tools
npm init -y

2. Install Dependencies

npm install @conveniencepro/ctp-core @conveniencepro/ctp-runtime
npm install -D typescript @types/node

3. Configure TypeScript

Create tsconfig.json:
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "declaration": true,
    "outDir": "dist",
    "rootDir": "src"
  },
  "include": ["src/**/*"]
}

4. Project Structure

my-ctp-tools/
├── src/
│   ├── tools/
│   │   ├── my-tool.ts
│   │   └── another-tool.ts
│   ├── registry.ts
│   └── index.ts
├── package.json
└── tsconfig.json

Create Your First Tool

Create src/tools/text-reverser.ts:
import type { ToolDefinition, ToolFunction } from '@conveniencepro/ctp-core';

// Define the result type
interface TextReverserResult {
  reversed: string;
  originalLength: number;
  isPalindrome: boolean;
}

// Tool definition
export const textReverserDefinition: ToolDefinition = {
  id: 'text-reverser',
  name: 'Text Reverser',
  description: 'Reverse any text string and check if it is a palindrome.',
  category: 'editors',
  tags: ['text', 'reverse', 'palindrome', 'string'],
  method: 'POST',
  parameters: [
    {
      name: 'text',
      type: 'textarea',
      label: 'Input Text',
      description: 'Text to reverse',
      required: true,
      placeholder: 'Enter text to reverse...',
    },
    {
      name: 'ignoreSpaces',
      type: 'boolean',
      label: 'Ignore Spaces',
      description: 'Ignore spaces when checking for palindrome',
      required: false,
      defaultValue: false,
    },
  ],
  outputDescription: 'Reversed text with palindrome detection',
  example: {
    input: { text: 'hello', ignoreSpaces: false },
    output: { reversed: 'olleh', originalLength: 5, isPalindrome: false },
  },
  executionMode: 'client',
};

// Tool implementation
export const textReverserFn: ToolFunction<TextReverserResult> = (params) => {
  const text = params.text as string;
  const ignoreSpaces = params.ignoreSpaces === true;

  if (!text) {
    return {
      success: false,
      error: 'Text is required',
      errorCode: 'MISSING_REQUIRED',
    };
  }

  const reversed = text.split('').reverse().join('');

  // Check palindrome
  const normalizedOriginal = ignoreSpaces
    ? text.toLowerCase().replace(/\s/g, '')
    : text.toLowerCase();
  const normalizedReversed = ignoreSpaces
    ? reversed.toLowerCase().replace(/\s/g, '')
    : reversed.toLowerCase();

  return {
    success: true,
    data: {
      reversed,
      originalLength: text.length,
      isPalindrome: normalizedOriginal === normalizedReversed,
    },
  };
};

export default {
  definition: textReverserDefinition,
  fn: textReverserFn,
};

Register Tools

Create src/registry.ts:
import { ToolRegistry } from '@conveniencepro/ctp-runtime';
import textReverser from './tools/text-reverser';

// Create registry
export const registry = new ToolRegistry();

// Register tools
registry.register(textReverser.definition, textReverser.fn);

// Export for use
export default registry;

Test Your Tool

Create src/index.ts:
import { createRuntime } from '@conveniencepro/ctp-runtime';
import registry from './registry';

// Create runtime
const runtime = createRuntime(registry);

// Test execution
async function main() {
  const result = await runtime.execute('text-reverser', {
    text: 'race car',
    ignoreSpaces: true,
  });

  console.log('Result:', JSON.stringify(result, null, 2));
}

main();
Run with:
npx ts-node src/index.ts
Expected output:
{
  "success": true,
  "data": {
    "reversed": "rac ecar",
    "originalLength": 8,
    "isPalindrome": true
  }
}

Next Steps