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 includingActionDef,SyncDef, and resource schemassrc/bridge.ts—BridgeClientclass with transport abstractionsrc/bridge-transports/— Adapters forcreateBearerTokenTransport,createComposioDirectTransport, andcreateRuntimeBrokerTransport
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
- Slack messaging —
reference/slack-messaging/app.ts: Custom state alphabet, message edit reactions, 11 comprehensive tests - Google Calendar events —
reference/gcalendar-events/app.ts: Calendar sync patterns and event mutation handling
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 instancemodule_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:
- Launches a headless HTML placeholder via
src/runtime/mcp-server.tsfor integration-only modules - Wires the Bridge client to the runtime's MCP broker
- 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
manifest.ts— MCP endpoint registration and metadatatest/my-custom-module.test.ts— Unit tests mirroring SDK patterns
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
mainbranch - 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 insrc/app.ts,src/types.ts, andsrc/bridge.ts - Reference implementations in
reference/provide copy-paste scaffolds for new modules - State persistence requires
module_idandmodule_resource_ididentifiers viaruntime/state-store/src/store.ts - Submission workflow: fork → scaffold → implement → test (
bun test && bunx tsc --noEmit) → PR againstmain
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →