@模型/模块sdk
用于构建Odel模块的SDK-Cloudflare Workers的HTTP MCP协议
使用TypeScript、Zod模式和模型上下文协议(MCP)为Odel平台构建类型安全的AI模块。
安装
npm install @odel/module-sdk zod
# or
pnpm add @odel/module-sdk zod
# or
yarn add @odel/module-sdk zod快速开始
1.安装依赖项
npm install @odel/module-sdk zod
npm install -D wranglerSDK具有对等依赖关系,您的包管理器会自动建议:
@cloudflare/workers-types-Cloudflare Workers的类型定义@cloudflare/vitest-pool-workers-Vitest测试工人池vitest-测试框架typescript-TypeScript编译器
使用以下方式安装它们:
npm install -D @cloudflare/workers-types @cloudflare/vitest-pool-workers typescript vitest2.配置TypeScript
创建 tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"lib": ["ES2022"],
"moduleResolution": "bundler",
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"types": ["@cloudflare/workers-types", "vitest/globals"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}3.配置Vitest
创建 vitest.config.ts:
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config';
export default defineWorkersConfig({
test: {
globals: true,
poolOptions: {
workers: {
wrangler: { configPath: './wrangler.toml' }
}
}
}
});4.配置牧马人
创建 wrangler.toml:
name = "my-module"
main = "src/index.ts"
compatibility_date = "2025-01-17"
compatibility_flags = ["nodejs_compat"]
[observability]
enabled = true5.添加测试类型声明
创建 src/cloudflare-test.d.ts:
declare module 'cloudflare:test' {
import type { ExecutionContext } from '@cloudflare/workers-types';
export function createExecutionContext(): ExecutionContext;
export function waitOnExecutionContext(ctx: ExecutionContext): Promise;
export const env: any;
}注: 此文件为cloudflare:test模块,仅在测试期间可用@cloudflare/vitest-pool-workers.
6.创建您的模块
创建 src/index.ts:
import { createModule, SuccessResponseSchema } from '@odel/module-sdk';
import { z } from 'zod';
export default createModule()
.tool({
name: 'add',
description: 'Add two numbers together',
inputSchema: z.object({
a: z.number().describe('First number'),
b: z.number().describe('Second number')
}),
outputSchema: SuccessResponseSchema(
z.object({
result: z.number().describe('Sum of a and b')
})
),
handler: async (input, _context) => {
return {
success: true as const,
result: input.a + input.b
};
}
})
.build();7.添加测试
创建 src/index.test.ts:
import { describe, test, expect } from 'vitest';
import { testMCPCompliance, testTool, expectSuccess } from '@odel/module-sdk/testing';
import { env, createExecutionContext, waitOnExecutionContext } from 'cloudflare:test';
import worker from './index';
// Test MCP protocol compliance
testMCPCompliance(
() => ({ worker, env, createExecutionContext, waitOnExecutionContext }),
['add'] // Expected tool names
);
describe('Calculator', () => {
test('add works correctly', async () => {
const result = await testTool(worker, 'add', { a: 2, b: 3 });
expectSuccess(result);
expect(result.result).toBe(5);
});
});8.在package.json中添加脚本
{
"scripts": {
"build": "tsc",
"test": "vitest run",
"test:watch": "vitest",
"deploy": "wrangler deploy",
"dev": "wrangler dev"
}
}9.运行测试
npm test特性
- 类型安全:完全支持TypeScript,可从Zod模式中自动进行类型推理
- 符合MCP标准:通过HTTP实现模型上下文协议
- 扩展MCP:可选
outputSchema支持更好的代码生成 - Cloudflare Workers:为Cloudflare Workers构建,提供一流的支持
- 测试工具:用于MCP合规性和工具测试的内置测试助手
- 错误处理:标准化错误代码和错误处理
- 验证器:电子邮件、URL、API密钥等的常见Zod验证器
核心api
createModule()
使用可选的环境类型创建新的模块构建器:
interface Env {
RESEND_API_KEY: string;
ANALYTICS: AnalyticsEngine;
}
export default createModule()
.tool({ ... })
.build();SuccessResponseSchema(dataSchema)
为成功/错误响应创建联合类型:
const outputSchema = SuccessResponseSchema(
z.object({
messageId: z.string()
})
);
// Valid responses:
// { success: true, messageId: "123" }
// { success: false, error: "Something went wrong" }工具上下文
每个工具处理程序都会收到一个 ToolContext 与:
interface ToolContext {
userId: string; // Hashed user ID
conversationId?: string; // Hashed conversation ID
displayName: string; // User's display name
timestamp: number; // Request timestamp
requestId: string; // Unique request ID
secrets: Record; // User-configured secrets
env: Env; // Cloudflare Worker bindings
}使用秘密
通过上下文访问用户配置的机密:
handler: async (input, context) => {
const apiKey = context.secrets.RESEND_API_KEY;
if (!apiKey) {
return {
success: false as const,
error: 'RESEND_API_KEY secret is required'
};
}
// Use the API key...
}使用验证
SDK包括通用验证器以减少样板:
import { createModule, validators } from '@odel/module-sdk';
export default createModule()
.tool({
name: 'send_email',
inputSchema: z.object({
to: validators.email(),
cc: validators.emailList().optional(),
apiKey: validators.apiKey('sk-')
}),
// ...
})
.build();可用验证器:
validators.email()-电子邮件地址validators.emailList()-逗号分隔的电子邮件列表validators.url()-HTTP/HTTPS网址validators.httpsUrl()-仅HTTPS URLvalidators.apiKey(prefix?)-带可选前缀的API密钥validators.json()-JSON字符串解析器validators.uuid()-UUID验证- 还有更多。..
错误处理
使用 ModuleError 对于标准化错误响应:
import { ModuleError, ErrorCode } from '@odel/module-sdk';
handler: async (input, context) => {
if (!context.secrets.API_KEY) {
throw ModuleError.missingSecret('API_KEY');
}
try {
// API call...
} catch (error) {
throw ModuleError.apiError('Failed to call API', {
statusCode: 500
});
}
}错误代码:
ErrorCode.INVALID_INPUT-验证错误ErrorCode.MISSING_SECRET-缺少必需的秘密ErrorCode.API_ERROR-外部API故障ErrorCode.RATE_LIMIT_EXCEEDED-速率限制- 还有更多。..
测试
SDK包括用于MCP合规性和工具测试的测试实用程序:
import { describe, test } from 'vitest';
import { testMCPCompliance, testTool, expectSuccess } from '@odel/module-sdk/testing';
import { env, createExecutionContext, waitOnExecutionContext } from 'cloudflare:test';
import worker from './src/index';
// Test MCP protocol compliance
testMCPCompliance(
() => ({ worker, env, createExecutionContext, waitOnExecutionContext }),
['add', 'subtract'] // Expected tool names
);
// Test individual tools
describe('Calculator tools', () => {
test('add tool works correctly', async () => {
const result = await testTool(worker, 'add', { a: 1, b: 2 });
expectSuccess(result);
expect(result.result).toBe(3);
});
test('handles invalid input', async () => {
const result = await testTool(worker, 'add', { a: 'not a number', b: 2 });
expectError(result, /invalid/i);
});
});示例:电子邮件模块
import { createModule, SuccessResponseSchema, validators, ModuleError } from '@odel/module-sdk';
import { z } from 'zod';
interface Env {
// No env secrets needed - uses user's configured secrets
}
export default createModule()
.tool({
name: 'send_email',
description: 'Send an email via Resend',
inputSchema: z.object({
to: validators.email(),
subject: validators.nonEmptyString(),
body: z.string()
}),
outputSchema: SuccessResponseSchema(
z.object({
messageId: z.string()
})
),
handler: async (input, context) => {
const apiKey = context.secrets.RESEND_API_KEY;
if (!apiKey) {
throw ModuleError.missingSecret('RESEND_API_KEY');
}
const response = await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
from: 'noreply@example.com',
to: input.to,
subject: input.subject,
html: input.body
})
});
if (!response.ok) {
throw ModuleError.apiError(`Failed to send email: ${response.statusText}`);
}
const data = await response.json();
return {
success: true as const,
messageId: data.id
};
}
})
.build();许可证
麻省理工学院
