- Add EXECUTOR_SPECIFICATION.md with formal v1.0 protocol spec - Add executor-openapi.yaml (OpenAPI 3.0 specification) - Create @tpmjs/executor-test compliance test package (15 tests) - Update Railway executor to v1.0 compliance (15/15 tests pass) - Update Unsandbox executor to v1.0 compliance (15/15 tests pass) - Update Vercel executor to v1.0 compliance - Add /info endpoint with capability advertisement to all executors - Add structured error codes (PACKAGE_NOT_FOUND, TOOL_NOT_FOUND, etc.) - Add protocolVersion and implementationVersion to /health responses - Add X-TPMJS-Protocol-Version header support - Add EXECUTOR_COMPLIANCE.md with test results documentation
12 KiB
TPMJS Executor Protocol Specification v1.0
Status: Draft Version: 1.0.0 Last Updated: 2026-02-03
Overview
The TPMJS Executor Protocol defines a standard HTTP interface for executing TPMJS tools. Executors are compute adapters that provide a consistent API for running npm-packaged tools regardless of the underlying infrastructure.
Design Philosophy
- HTTP-First: No SDK lock-in, deployable anywhere
- Minimal Surface: Small core, optional extensions
- Executor ≠ Sandbox: Standardize coordination, not security
- Declare, Don't Enforce: Executors report capabilities, TPMJS decides policy
Relationship to Other Specs
| Spec | Purpose |
|---|---|
| MCP | Model ↔ Tool interface |
| TPMJS Executor | Tool ↔ Compute interface |
| TPMJS Tools | Tool contract (separate spec) |
Protocol Versioning
Version Header
All requests SHOULD include:
X-TPMJS-Protocol-Version: 1.0
Executors MUST respond with their supported protocol version in /health and /info responses.
Rationale: Header-based versioning enables graceful evolution without URL fragmentation.
Specification Levels
Level 1: Core (REQUIRED)
Every executor MUST implement:
| Endpoint | Method | Purpose |
|---|---|---|
/health |
GET | Liveness + protocol discovery |
/execute-tool |
POST | Synchronous tool execution |
Level 2: Standard (RECOMMENDED)
Executors SHOULD implement:
| Endpoint | Method | Purpose |
|---|---|---|
/info |
GET | Capability advertisement |
Plus:
- API key authentication
- Structured error responses
- Execution timeout enforcement
- CORS headers
Level 3: Extended (OPTIONAL)
Reserved for future versions:
POST /execute-toolwithAccept: text/event-stream(streaming)POST /execute-async(webhook callbacks)POST /validate-tool(dry-run validation)POST /execute-batch(multiple tools)
Core Endpoints
GET /health
Purpose: Verify executor is running and discover protocol version.
Response (200 OK):
{
"status": "ok",
"protocolVersion": "1.0",
"implementationVersion": "1.0.0",
"runtime": "node",
"timestamp": "2026-02-03T12:00:00.000Z"
}
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | Yes | Always "ok" if healthy |
protocolVersion |
string | Yes | TPMJS protocol version (e.g., "1.0") |
implementationVersion |
string | Yes | Executor software version |
runtime |
string | No | Runtime identifier (e.g., "node", "deno", "bun") |
timestamp |
string | No | ISO 8601 timestamp |
Requirements:
- MUST respond within 1 second
- MUST return 200 OK if healthy
- MUST include
protocolVersion
POST /execute-tool
Purpose: Execute a single TPMJS tool synchronously.
Request Headers:
Content-Type: application/json
Authorization: Bearer <api-key> (if auth enabled)
X-TPMJS-Protocol-Version: 1.0
Request Body:
{
"packageName": "@tpmjs/hello",
"version": "latest",
"name": "helloWorldTool",
"params": {
"greeting": "Hello"
},
"env": {
"OPENAI_API_KEY": "sk-..."
}
}
Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
packageName |
string | Yes | npm package name |
version |
string | No | Package version (default: "latest") |
name |
string | Yes | Tool export name |
params |
object | No | Parameters passed to tool.execute() |
env |
object | No | Environment variables for execution |
Success Response (200 OK):
{
"success": true,
"output": {
"message": "Hello, World!"
},
"executionTimeMs": 1234
}
Error Response (200 OK):
{
"success": false,
"error": {
"code": "TOOL_EXECUTION_ERROR",
"message": "Tool threw an error: Invalid input"
},
"executionTimeMs": 123
}
Response Fields:
| Field | Type | Required | Description |
|---|---|---|---|
success |
boolean | Yes | Whether execution succeeded |
output |
any | If success | Return value from tool.execute() |
error |
object | If failed | Error details |
error.code |
string | If failed | Machine-readable error code |
error.message |
string | If failed | Human-readable error message |
executionTimeMs |
number | Yes | Total execution time in milliseconds |
Error Codes:
| Code | Description |
|---|---|
PACKAGE_NOT_FOUND |
npm package could not be installed |
TOOL_NOT_FOUND |
Named export not found in package |
TOOL_INVALID |
Export exists but has no .execute() method |
TOOL_EXECUTION_ERROR |
Tool threw during execution |
EXECUTION_TIMEOUT |
Execution exceeded time limit |
INTERNAL_ERROR |
Unexpected executor error |
Standard Endpoints
GET /info
Purpose: Advertise executor capabilities for intelligent routing.
Response (200 OK):
{
"name": "Railway Executor",
"version": "1.0.0",
"protocolVersion": "1.0",
"capabilities": {
"isolation": "process",
"executionModes": ["sync"],
"maxExecutionTimeMs": 120000,
"maxRequestBodyBytes": 10485760,
"supportsStreaming": false,
"supportsCallbacks": false,
"supportsCaching": false
},
"runtime": {
"platform": "linux",
"nodeVersion": "20.10.0",
"region": "us-west-1"
}
}
Capability Fields:
| Field | Type | Description |
|---|---|---|
isolation |
string | "none" | "process" | "container" | "vm" |
executionModes |
array | ["sync"] (future: "stream", "async") |
maxExecutionTimeMs |
number | Maximum execution time before timeout |
maxRequestBodyBytes |
number | Maximum request body size |
supportsStreaming |
boolean | Reserved for v1.1 |
supportsCallbacks |
boolean | Reserved for v1.1 |
supportsCaching |
boolean | Reserved for v1.1 |
Isolation Levels:
| Level | Description |
|---|---|
none |
Tools run in executor process (development only) |
process |
Tools run in separate OS process |
container |
Tools run in isolated container |
vm |
Tools run in isolated VM (strongest) |
Authentication
v1.0: API Key Only
Executors MAY require authentication via Bearer token.
Request Header:
Authorization: Bearer <api-key>
Configuration:
Executors SHOULD use EXECUTOR_API_KEY environment variable:
- If set: All requests MUST include valid Bearer token
- If unset: No authentication required
Unauthorized Response (401):
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}
Future Versions: JWT, OAuth, and per-tool authentication are deferred to v1.1+.
CORS Requirements
All executors MUST support CORS for browser-based clients.
Required Headers:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, X-TPMJS-Protocol-Version
OPTIONS Preflight:
All endpoints MUST handle OPTIONS requests and return CORS headers with 200 OK.
Execution Lifecycle
Standard Flow
- Receive Request: Parse JSON body, validate required fields
- Check Auth: Verify API key if configured
- Create Isolation: Create temporary execution environment
- Install Package: Run
npm install <package>@<version> - Load Tool: Import package, resolve named export
- Execute: Call
tool.execute(params)with environment - Capture Result: Collect output or error
- Cleanup: Remove temporary files/processes
- Respond: Return JSON response
Tool Resolution
Executors MUST resolve a callable tool with an .execute() method.
Recommended Resolution Order:
pkg[name]- Direct named exportpkg.default?.[name]- Named property on default exportpkg.default- Default export itself (ifnamematches)
Factory Functions:
If export is a function without .execute():
- Try calling
tool()with no arguments - Check if result has
.execute()method
Note: Tool export patterns are intentionally not fully standardized in v1.0 to allow ecosystem evolution.
Timeouts
Required Timeouts
| Phase | Minimum | Recommended |
|---|---|---|
| npm install | 30s | 60s |
| Tool execution | 60s | 120s |
| Total request | 90s | 180s |
Executors MUST:
- Enforce execution timeouts
- Return
EXECUTION_TIMEOUTerror code when exceeded - Clean up resources on timeout
Error Handling
HTTP Status Codes
| Code | Usage |
|---|---|
| 200 | Successful execution OR tool error (with success: false) |
| 400 | Invalid request (missing fields, malformed JSON) |
| 401 | Authentication required but missing/invalid |
| 404 | Unknown endpoint |
| 500 | Internal executor error |
Structured Errors
All error responses MUST include:
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description"
}
}
Implementation Checklist
Core (Required for Compliance)
GET /healthreturns status and protocol versionPOST /execute-toolaccepts standard request format- Returns
{ success, output/error, executionTimeMs } - Handles missing/invalid request body (400)
- CORS headers on all responses
- OPTIONS preflight handling
Standard (Recommended)
GET /infowith capabilitiesEXECUTOR_API_KEYenvironment variable support- Bearer token validation (401 on failure)
- Execution timeout enforcement
- npm install timeout (60s recommended)
- Temporary file cleanup
- Structured error codes
Extended (Optional)
- Package caching
- Concurrent execution limiting
- Support for both
/pathand/api/pathroutes - Region/metadata in
/inforesponse
Compliance Testing
Use the official compliance test suite:
npx @tpmjs/executor-test https://my-executor.example.com
Output:
TPMJS Executor Compliance Test v1.0.0
Target: https://my-executor.example.com
Core Requirements:
✓ GET /health returns 200
✓ GET /health includes protocolVersion
✓ POST /execute-tool accepts valid request
✓ POST /execute-tool returns success response
✓ POST /execute-tool returns error for invalid tool
✓ CORS headers present
✓ OPTIONS preflight works
Standard Requirements:
✓ GET /info returns capabilities
✓ Authentication enforced when configured
✓ Execution timeout enforced
✗ Missing: maxExecutionTimeMs in capabilities
Result: 10/11 tests passed (Core: PASS, Standard: PARTIAL)
Reference Implementations
| Name | Platform | Isolation | Source |
|---|---|---|---|
| Railway Executor | Railway | Process | templates/railway-executor/ |
| Vercel Executor | Vercel | VM (Sandbox) | templates/vercel-executor/ |
| Unsandbox Executor | Unsandbox | Container | templates/unsandbox-executor/ |
Future Roadmap
v1.1 (Planned)
- Streaming responses (
Accept: text/event-stream) - Async execution with webhooks
- Caching hints (
X-TPMJS-Cache-*headers) - Tool validation endpoint
v2.0 (Exploration)
- Multi-tool batch execution
- Persistent execution contexts
- Resource quotas and billing hooks
- MCP bridge protocol
Changelog
v1.0.0 (2026-02-03)
- Initial formal specification
- Core:
/health,/execute-tool - Standard:
/info, API key auth - Capability negotiation
- Compliance test suite
Appendix: OpenAPI Specification
See executor-openapi.yaml for the formal OpenAPI 3.0 specification.
Appendix: JSON Schemas
See packages/types/src/executor.ts for TypeScript types and Zod schemas.