1. Conduid
  2. Cloud
  3. Module SDK
MCP server · Cloud

Module SDK

SDK for building Odel modules — a thin, additive wrapper over the Model Context Protocol TypeScript SDK for Cloudflare Workers

37Low

Scored 23 hours ago · breakdown

About Module SDK

Module SDK is an MCP server in the Cloud category: sDK for building Odel modules — a thin, additive wrapper over the Model Context Protocol TypeScript SDK for Cloudflare Workers.

Recent commit activity is the strongest signal that reported issues will get attention.

Install

Claude Code
claude mcp add module-sdk -- npx -y @odel/module-sdk
npx
npx -y @odel/module-sdk

This server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.

Ask AI

✦

Ask AI about Module SDK

Powered by Claude · Grounded in docs

I know everything about Module SDK. Ask me about installation, configuration, usage, or troubleshooting.

Security checks

  • ✓README presentThe repository ships documentation.

5 checks have not been run yet.

README

Odel Module SDK NPM Version MIT licensed

Fork of the Model Context Protocol TypeScript SDK with Odel-specific extensions for the Odel Platform

SDK for building Odel modules - full MCP protocol implementation with additional utilities for context management, error handling, and input validation.

Overview

This SDK provides:

  • Full MCP protocol implementation (tools, resources, prompts)
  • Odel context management (user info, secrets, request tracking)
  • Standardized error handling with error codes
  • Common validators for inputs (email, URL, API keys, etc.)
  • Response schema helpers for consistent API responses

Installation

npm install @odel/module-sdk zod

This SDK has a required peer dependency on zod for schema validation.

Quick Start

import { McpServer } from '@odel/module-sdk/server';
import { z } from 'zod';
import { extractToolContext, getRequiredSecret, ModuleError, SuccessResponseSchema, validators } from '@odel/module-sdk/odel';

// Define your response schema
const SendEmailResponseSchema = SuccessResponseSchema(
    z.object({
        messageId: z.string(),
        sentAt: z.string()
    })
);

// Create your MCP server
const server = new McpServer({
    name: 'email-module',
    version: '1.0.0'
});

// Register a tool
server.tool(
    'send-email',
    'Send an email',
    {
        to: validators.email(),
        subject: validators.nonEmptyString(),
        body: z.string()
    },
    async (args, extra) => {
        // Extract Odel context (userId, secrets, etc.)
        const ctx = extractToolContext(extra.requestBody, process.env);

        // Get required secrets
        const apiKey = getRequiredSecret(ctx, 'RESEND_API_KEY');

        try {
            // Your implementation here
            const result = await sendEmail(apiKey, args);

            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            success: true,
                            messageId: result.id,
                            sentAt: new Date().toISOString()
                        })
                    }
                ]
            };
        } catch (error) {
            throw ModuleError.apiError('Failed to send email', {
                originalError: error.message
            });
        }
    }
);

Odel Extensions

All Odel-specific utilities are available from @odel/module-sdk/odel:

import {
    // Context
    extractContext,
    createToolContext,
    extractToolContext,
    getRequiredSecret,
    getOptionalSecret,
    DEFAULT_MODULE_CONTEXT,

    // Types
    type ModuleContext,
    type ToolContext,
    type RequestBodyWithContext,

    // Errors
    ModuleError,
    ErrorCode,

    // Validators
    validators,

    // Schemas
    SuccessResponseSchema,
    SimpleSuccessSchema,
    type SuccessResponse,
    type ErrorResponse
} from '@odel/module-sdk/odel';

Context

The Odel platform injects context into every module request, including user information and decrypted secrets.

ModuleContext

interface ModuleContext {
    userId: string; // Hashed user ID (privacy-preserving)
    conversationId?: string; // Optional conversation ID
    displayName?: string; // User's display name
    timestamp: number; // Request timestamp
    requestId: string; // Unique request identifier
    secrets: Record<string, string>; // Decrypted user secrets
}

ToolContext

For Cloudflare Workers, ToolContext<Env> extends ModuleContext with typed environment bindings:

interface ToolContext<Env> extends ModuleContext {
    env: Env; // Cloudflare Worker bindings
}

Context Functions

// Extract context from JSON-RPC request body
const moduleContext = extractContext(requestBody);

// Create tool context with env bindings
const toolContext = createToolContext(moduleContext, env);

// Or do both in one step
const toolContext = extractToolContext(requestBody, env);

// Access secrets safely
const apiKey = getRequiredSecret(ctx, 'API_KEY'); // Throws if missing
const webhook = getOptionalSecret(ctx, 'WEBHOOK_URL'); // Returns undefined if missing

Error Handling

Standardized error codes and a ModuleError class for consistent error responses.

Error Codes

Range Category Codes
1xxx Validation INVALID_INPUT, MISSING_REQUIRED_FIELD, INVALID_FORMAT
2xxx Auth MISSING_SECRET, INVALID_SECRET, UNAUTHORIZED
3xxx API API_ERROR, NETWORK_ERROR, TIMEOUT, NOT_FOUND
4xxx Rate Limit RATE_LIMIT_EXCEEDED, QUOTA_EXCEEDED
5xxx Internal INTERNAL_ERROR, NOT_IMPLEMENTED, CONFIGURATION_ERROR

Factory Methods

// Validation errors
ModuleError.validationError('Invalid email format', { field: 'email' });
ModuleError.missingField('subject');

// Auth errors
ModuleError.missingSecret('RESEND_API_KEY');
ModuleError.invalidSecret('API_KEY', 'must start with sk-');

// API errors
ModuleError.apiError('Service unavailable', { statusCode: 503 });
ModuleError.networkError('Connection refused');
ModuleError.timeout('API call', 30000);
ModuleError.notFound('User', 'user_123');

// Rate limiting
ModuleError.rateLimitError(60); // retryAfter in seconds
ModuleError.quotaExceeded('API calls');

// Internal
ModuleError.internalError('Unexpected state');
ModuleError.notImplemented('bulk export');
ModuleError.configurationError('Missing database binding');

JSON Serialization

const error = ModuleError.apiError('Service unavailable', { statusCode: 503 });
console.log(error.toJSON());
// {
//   success: false,
//   error: 'Service unavailable',
//   code: 3001,
//   metadata: { statusCode: 503 }
// }

Validators

Pre-built Zod schemas for common input validation:

import { validators } from '@odel/module-sdk/odel';
import { z } from 'zod';

const inputSchema = z.object({
    // Email validation
    email: validators.email(),
    recipients: validators.emailList(), // Array or comma-separated string

    // URL validation
    website: validators.url(), // http or https
    webhook: validators.httpsUrl(), // https only

    // API keys
    apiKey: validators.apiKey(), // Min 10 chars
    openaiKey: validators.apiKey('sk-'), // With prefix

    // Strings
    name: validators.nonEmptyString(),
    bio: validators.trimmedString(), // Auto-trims, rejects empty
    title: validators.boundedString(1, 100), // Length constraints
    nickname: validators.optionalString(), // Empty string → undefined

    // Numbers
    count: validators.positiveInt(), // > 0, integer
    offset: validators.nonNegativeInt(), // >= 0, integer
    port: validators.port(), // 1-65535

    // Other
    id: validators.uuid(),
    createdAt: validators.isoDate(), // ISO 8601 datetime
    status: validators.enumFrom(['draft', 'published', 'archived'] as const),
    config: validators.json<{ enabled: boolean }>() // Parse JSON string
});

Response Schemas

Standardized success/error response pattern:

import { SuccessResponseSchema, SimpleSuccessSchema } from '@odel/module-sdk/odel';
import { z } from 'zod';

// Define a response schema with data fields
const EmailResponseSchema = SuccessResponseSchema(
    z.object({
        messageId: z.string(),
        sentAt: z.string()
    })
);

// Type inference
type EmailResponse = z.infer<typeof EmailResponseSchema>;
// = { success: true; messageId: string; sentAt: string }
// | { success: false; error: string }

// Usage with type narrowing
function handleResponse(response: EmailResponse) {
    if (response.success) {
        console.log(`Sent: ${response.messageId}`);
    } else {
        console.error(`Failed: ${response.error}`);
    }
}

// Simple success/error without data
const result = SimpleSuccessSchema.parse({ success: true });

MCP Core Concepts

This SDK includes the full MCP TypeScript SDK. Key concepts:

Servers and Transports

  • Streamable HTTP for remote servers (recommended)
  • HTTP + SSE for backwards compatibility
  • stdio for local integrations

Tools, Resources, Prompts

  • Tools: Let LLMs take actions (computation, API calls, side effects)
  • Resources: Expose read-only data to clients
  • Prompts: Reusable templates for consistent model interactions

Capabilities

  • Sampling: Server tools can request LLM completions from clients
  • Elicitation: Request structured input via forms or secure browser flows
  • Tasks: Long-running operations with polling/resumption

For detailed MCP documentation, see:

Documentation

License

This project is licensed under the MIT License—see the LICENSE file for details.

Based on the Model Context Protocol TypeScript SDK.

README copy captured when this server was indexed; it may lag the repository. The original is authoritative.

Questions

About Module SDK

How do I install Module SDK?

Run claude mcp add module-sdk -- npx -y @odel/module-sdk, then add the server to your MCP client's configuration.

Is Module SDK safe to use with an AI agent?

Its trust score is 37 out of 100 (low). It passes 1 of the 1 static security checks run so far. It has no ConduID identity yet, so agent calls to it are not receipted.

Is Module SDK still maintained?

Yes — the last commit was 6 days ago. The repository has 0 stars and 0 forks.