/**
* Code API Generator
*
* Generates TypeScript files that agents can discover and import.
* Per Anthropic's recommendations for code generation.
*/
import { writeFileSync, mkdirSync, existsSync } from 'fs';
import { join, dirname } from 'path';
const INDEX_TEMPLATE = `/**
* RelayPlane Code API
*
* Generated by @relayplane/mcp-server
* Use these functions to interact with RelayPlane workflows from your code.
*/
export { run } from './run.js';
export { workflow } from './workflow.js';
export { listModels } from './models.js';
export { listSkills } from './skills.js';
`;
const RUN_TEMPLATE = `/**
* Single Model Call API
*/
export interface RunInput {
model: string;
prompt: string;
systemPrompt?: string;
schema?: object;
}
export interface RunResponse {
success: boolean;
output: string | object;
usage: {
promptTokens: number;
completionTokens: number;
estimatedProviderCostUsd: number;
};
durationMs: number;
runId: string;
traceUrl: string;
}
/**
* Execute a single AI model call.
*
* Cost tracks your provider bill (OpenAI/Anthropic), not RelayPlane fees — we're BYOK.
*
* @example
* const result = await run({
* model: "openai:gpt-4o",
* prompt: "Summarize this document..."
* });
* console.log(result.output);
*/
export async function run(input: RunInput): Promise<RunResponse> {
// This function is a placeholder for MCP tool call
// In actual usage, this would be called via the MCP client
throw new Error(
'run() must be called via MCP client. ' +
'Use the relay_run tool through your MCP-enabled AI assistant.'
);
}
`;
const WORKFLOW_TEMPLATE = `/**
* Multi-Step Workflow API
*/
export interface WorkflowStep {
name: string;
model?: string;
prompt?: string;
systemPrompt?: string;
depends?: string[];
mcp?: string;
params?: Record<string, any>;
schema?: object;
}
export interface WorkflowInput {
name: string;
steps: WorkflowStep[];
input: Record<string, any>;
}
export interface WorkflowResponse {
success: boolean;
steps: Record<string, { output: any; durationMs: number }>;
finalOutput: any;
totalUsage: { totalTokens: number; estimatedProviderCostUsd: number };
runId: string;
traceUrl: string;
contextReduction: string;
}
/**
* Execute a multi-step AI workflow.
*
* **90%+ context reduction:** Intermediate results stay in the workflow engine,
* not your context. Only the final result returns to you.
*
* Cost tracks your provider bills (OpenAI/Anthropic), not RelayPlane fees — we're BYOK.
*
* @example
* const result = await workflow({
* name: "extract-and-validate",
* steps: [
* { name: "extract", model: "openai:gpt-4o", prompt: "Extract invoice data..." },
* { name: "validate", model: "anthropic:claude-3-5-sonnet-20241022", depends: ["extract"], prompt: "Validate..." }
* ],
* input: { fileUrl: "https://..." }
* });
*/
export async function workflow(input: WorkflowInput): Promise<WorkflowResponse> {
// This function is a placeholder for MCP tool call
// In actual usage, this would be called via the MCP client
throw new Error(
'workflow() must be called via MCP client. ' +
'Use the relay_workflow_run tool through your MCP-enabled AI assistant.'
);
}
`;
const MODELS_TEMPLATE = `/**
* Models API
*/
export interface ModelInfo {
id: string;
provider: string;
name: string;
capabilities: string[];
contextWindow: number;
inputCostPer1kTokens: number;
outputCostPer1kTokens: number;
configured: boolean;
}
export interface ModelsResponse {
models: ModelInfo[];
}
/**
* List available AI models with capabilities and pricing.
*
* Use to check valid model IDs before testing.
*
* @example
* const { models } = await listModels({ provider: 'openai' });
* console.log(models.map(m => m.id));
*/
export async function listModels(options?: { provider?: string }): Promise<ModelsResponse> {
// This function is a placeholder for MCP tool call
throw new Error(
'listModels() must be called via MCP client. ' +
'Use the relay_models_list tool through your MCP-enabled AI assistant.'
);
}
`;
const SKILLS_TEMPLATE = `/**
* Skills API
*/
export interface SkillInfo {
name: string;
category: string;
description: string;
models: string[];
contextReduction: string;
usage: string;
estimatedCost: string;
}
export interface SkillsResponse {
skills: SkillInfo[];
}
/**
* List available pre-built workflow skills.
*
* Skills are reusable patterns for common tasks (invoice processing,
* content pipelines, etc.).
*
* @example
* const { skills } = await listSkills({ category: 'extraction' });
* console.log(skills.map(s => s.name));
*/
export async function listSkills(options?: { category?: string }): Promise<SkillsResponse> {
// This function is a placeholder for MCP tool call
throw new Error(
'listSkills() must be called via MCP client. ' +
'Use the relay_skills_list tool through your MCP-enabled AI assistant.'
);
}
`;
const README_TEMPLATE = `# RelayPlane Code API
Generated by \`@relayplane/mcp-server\`
## Overview
This directory contains TypeScript types and function stubs for interacting with RelayPlane workflows.
These files are intended for use with MCP-enabled AI assistants.
## Usage
When using an MCP-enabled AI assistant (like Claude with MCP), you can reference these types
in your code. The actual execution happens through MCP tool calls.
\`\`\`typescript
import { run, workflow } from './servers/relayplane';
// Single model call
const result = await run({
model: "openai:gpt-4o",
prompt: "Summarize this document..."
});
// Multi-step workflow
const workflowResult = await workflow({
name: "extract-and-validate",
steps: [
{ name: "extract", model: "openai:gpt-4o", prompt: "Extract data..." },
{ name: "validate", model: "anthropic:claude-3-5-sonnet-20241022", depends: ["extract"], prompt: "Validate..." }
],
input: { document: "..." }
});
\`\`\`
## Context Efficiency
RelayPlane workflows provide **90%+ context reduction** on multi-step pipelines.
Intermediate results stay in the workflow engine, not your context window.
## Cost
All costs shown are **provider costs** (OpenAI, Anthropic, etc.).
RelayPlane is BYOK (Bring Your Own Keys) — we don't charge for API usage.
`;
/**
* Ensure directory exists
*/
function ensureDir(dirPath: string): void {
if (!existsSync(dirPath)) {
mkdirSync(dirPath, { recursive: true });
}
}
/**
* Write file with directory creation
*/
function writeFile(filePath: string, content: string): void {
ensureDir(dirname(filePath));
writeFileSync(filePath, content, 'utf-8');
}
/**
* Generate the code API files
*/
export async function generateCodeAPI(outDir: string): Promise<void> {
const absoluteOutDir = join(process.cwd(), outDir);
// Generate files
writeFile(join(absoluteOutDir, 'index.ts'), INDEX_TEMPLATE);
writeFile(join(absoluteOutDir, 'run.ts'), RUN_TEMPLATE);
writeFile(join(absoluteOutDir, 'workflow.ts'), WORKFLOW_TEMPLATE);
writeFile(join(absoluteOutDir, 'models.ts'), MODELS_TEMPLATE);
writeFile(join(absoluteOutDir, 'skills.ts'), SKILLS_TEMPLATE);
writeFile(join(absoluteOutDir, 'README.md'), README_TEMPLATE);
}