How to Contribute to holaOS Module Development: A Complete Guide for Building MCP-Compatible Extensions

Contribute to holaOS module development by forking the repository, building against the @holaboss/app-builder-sdk, and submitting a pull request with passing tests.

The holaOS open-source operating system from Holaboss AI enables developers to extend its capabilities through self-contained modules that communicate via the MCP (Module Communication Protocol). This guide walks you through the exact architecture, SDK primitives, and submission process required to contribute production-ready modules to the ecosystem.


Understanding the holaOS Module Architecture

Modules in holaOS are app back-ends that expose functionality through five core primitives defined in the SDK. The architecture separates concerns into distinct layers, each with specific responsibilities and source file locations.

The Five SDK Primitives

Every module is built on these foundation blocks:

Primitive Purpose Implementation
connection() Declare provider authentication src/app.ts
resource() Define data models and schemas src/types.ts
action() Attach handlers to resource operations src/types.ts
sync() Configure periodic data fetching src/types.ts
start() Bootstrap the module and register MCP endpoint src/app.ts

These primitives are exposed through the createApp() factory function in runtime/harnesses/src/embedded-skills/app-builder-sdk/sdk-package/src/app.ts:

export function createApp(id: string) {
  return {
    connection: () => {/* … */},
    resource: (name, def) => {/* … */},
    action: (resource, name, def) => {/* … */},
    sync: (name, def) => {/* … */},
    start: () => {/* … */}
  };
}

Key Source Files for Contributors

  • src/types.ts — Type definitions including ActionDef, SyncDef, and resource schemas
  • src/bridge.ts — BridgeClient class with transport abstraction
  • src/bridge-transports/ — Adapters for createBearerTokenTransport, createComposioDirectTransport, and createRuntimeBrokerTransport

The Bridge client enables modules to run locally during development or inside the production Holaboss runtime without code changes.


Reference Implementations: Learning from Existing Modules

The SDK ships with battle-tested reference modules that demonstrate proper patterns. Each reference follows a consistent structure:


reference/<shape>-<provider>/
 ├─ app.ts      // SDK usage and business logic
 ├─ manifest.ts // MCP registration details
 └─ e2e.ts      // End-to-end validation

Notable Examples

These implementations exercise all five primitives and demonstrate proper error handling, state management, and test coverage expected of contributed modules.


State Persistence and Runtime Integration

The State Store API

Module data persists through the generic state-store at runtime/state-store/src/store.ts. The schema uses composite identifiers:

  • module_id — Uniquely identifies your module instance
  • module_resource_id — Identifies individual objects within the module namespace

Lines 12222-12238 of store.ts define these columns and their relational constraints.

Runtime Bridging

When start() is called, the SDK:

  1. Launches a headless HTML placeholder via src/runtime/mcp-server.ts for integration-only modules
  2. Wires the Bridge client to the runtime's MCP broker
  3. Registers all declared resources and actions for external invocation

Modules with UI requirements can add a src/client/ layer alongside the back-end primitives.


Step-by-Step: Contributing Your First holaOS Module

Follow this proven workflow to maximize approval velocity:

1. Fork and Setup


# Fork on GitHub, then clone your fork

git clone https://github.com/YOUR_USERNAME/holaOS.git
cd holaOS

# Install dependencies (Bun required)

bun install

2. Scaffold Your Module


# Create directory under reference implementations

cd runtime/harnesses/src/embedded-skills/app-builder-sdk/sdk-package/reference/
cp -r slack-messaging my-custom-module
cd my-custom-module

3. Implement Using SDK Primitives

// File: reference/my-custom-module/app.ts
import { createApp } from '../../src/app';

const app = createApp('my-custom-module');

// Declare external connection (OAuth, API key, etc.)
app.connection();

// Define a resource with schema
app.resource('Task', {
  schema: {
    title: 'string',
    completed: 'boolean',
    dueDate: 'string?'
  },
  initial: () => ({
    title: 'New Task',
    completed: false
  })
});

// Attach actions to the resource
app.action('Task', 'Complete', {
  input: {},
  handler: async (row) => {
    row.completed = true;
    return row;
  }
});

app.action('Task', 'Reschedule', {
  input: { newDate: 'string' },
  handler: async (row, { newDate }) => {
    row.dueDate = newDate;
    return row;
  }
});

// Configure periodic sync
app.sync('TaskSync', {
  interval: 300000, // 5 minutes
  fetch: async () => {
    // Implementation fetches from external API
  }
});

// Bootstrap the module
app.start();

4. Add Manifest and Tests

5. Validate Before Submission


# Run full test suite (63+ existing tests + yours)

bun test

# Type-check the entire package

bunx tsc --noEmit

# Equivalent to CI check

make check

6. Submit Pull Request

  • Target the main branch
  • Include concise purpose description
  • Ensure CI passes (tests + type-checking)
  • Update docs/plans/ if adding novel capabilities

Complete "Hello World" Module Example

This minimal implementation demonstrates all primitives without external dependencies:

// File: reference/hello-world/app.ts
import { createApp } from '../../src/app';
import { BridgeClient, createRuntimeBrokerTransport } from '../../src/bridge';

const hello = createApp('hello-world');

// Self-contained resource with default state
hello.resource('Greeting', {
  schema: { message: 'string', updatedAt: 'number' },
  initial: () => ({
    message: 'Hello, holaOS!',
    updatedAt: Date.now()
  })
});

// Action with input validation
hello.action('Greeting', 'UpdateMessage', {
  input: { newMessage: 'string' },
  handler: async (row, { newMessage }) => {
    row.message = newMessage;
    row.updatedAt = Date.now();
    return row;
  }
});

// No-op sync for demonstration (module-local only)
hello.sync('Heartbeat', {
  interval: 60000,
  fetch: async () => {
    // Could emit telemetry here
  }
});

hello.start();

// Optional Bridge client for external integration
export const client = new BridgeClient({
  transport: createRuntimeBrokerTransport({
    provider: 'hello-world'
    // Runtime injects broker URL and grant via env vars
  })
});

Critical Contribution Guidelines

Violating these patterns will block PR approval:

Constraint Rationale Enforcement
No as any casts Preserve type safety across module boundaries bunx tsc --noEmit fails
Headless by default Reduce attack surface and resource consumption Placeholder HTML in mcp-server.ts
Use store.ts APIs Ensure data portability and backup consistency State isolation via module_id/module_resource_id
63+ tests must pass Prevent regressions in shared runtime bun test in CI
Document new capabilities Enable ecosystem discoverability docs/plans/ or module README

Summary

  • holaOS modules are MCP-compatible back-ends built with five SDK primitives from @holaboss/app-builder-sdk
  • The SDK core lives at runtime/harnesses/src/embedded-skills/app-builder-sdk/sdk-package/ with entry points in src/app.ts, src/types.ts, and src/bridge.ts
  • Reference implementations in reference/ provide copy-paste scaffolds for new modules
  • State persistence requires module_id and module_resource_id identifiers via runtime/state-store/src/store.ts
  • Submission workflow: fork → scaffold → implement → test (bun test && bunx tsc --noEmit) → PR against main

Frequently Asked Questions

What programming language are holaOS modules written in?

TypeScript is the sole supported language. The SDK (@holaboss/app-builder-sdk) provides type-safe primitives, and the test suite enforces strict null checks via bunx tsc --noEmit. Reference modules demonstrate idiomatic patterns without as any casts.

Do I need to understand MCP to contribute a module?

Basic MCP familiarity helps but isn't mandatory. The SDK abstracts protocol details through the BridgeClient in src/bridge.ts. Your module declares resources and actions; the runtime handles MCP serialization. For advanced use cases, review manifest.ts in reference implementations.

How does my module access external APIs?

Through the connection primitive and Bridge transports. Call app.connection() to declare authentication requirements, then use createBearerTokenTransport or createComposioDirectTransport for external calls. In production, createRuntimeBrokerTransport routes through Holaboss's managed infrastructure.

What happens to my module's data?

All state persists through the SQLite-backed state-store at runtime/state-store/src/store.ts. Your module receives isolated storage keyed by module_id, with individual resources identified by module_resource_id. The SDK handles serialization; you interact with plain JavaScript objects.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →