How Extensions Manifest and Projection Work in OpenWork Den: A Complete Technical Guide

OpenWork Den manages extensions through a two-phase workflow: JSON manifest generation stored in the Den database, followed by policy-filtered projection to desktop clients via MCP endpoints.

The different-ai/openwork repository implements a centralized extension management system where OpenWork Den acts as the control plane for all plugins, MCPs, and skills. Understanding how extensions manifest and projection work is essential for developers building custom integrations or deploying self-hosted instances.

What Is the OpenWork Den Extensions Manifest?

Every extension in OpenWork Den is described by a JSON manifest that lives in the Den database. This manifest contains the extension's ID, name, version, description, capabilities, commands, MCP endpoints, and policy flags distinguishing built-in from local extensions.

When an organization admin publishes an extension, the backend writes the manifest to the extensions table. Den exposes this data through the REST API endpoint /api/v1/extensions/manifest?<orgId>=…, returning a JSON payload that matches the client's expected schema.

The Manifest Generation Phase

Publishing Extension Metadata

Administrators upload extension manifests via the Den UI or API. The manifest captures critical metadata including version constraints and capability declarations. The UI component in ee/apps/den-web/app/(den)/dashboard/_components/extensions-download-promo.tsx advertises the download-manifest link to users, connecting the web dashboard to the desktop client ecosystem.

CLI Retrieval and Validation

The desktop client uses the bootstrap CLI to fetch manifests. In packages/openwork-bootstrap/bin/openwork.mjs, the tool performs a fetch against the manifest endpoint and validates the response. If the fetch fails, the CLI throws a manifest_fetch_failed error, preventing corrupted or unreachable extensions from entering the system.

The Projection Phase: From Server to UI

Fetching Capabilities via MCP

Once manifests are stored, clients retrieve them through the Den MCP endpoint search_capabilities → extensions. This RPC call returns the current manifest data to any OpenWork-compatible agent or desktop client.

Policy Filtering and Schema Validation

Before rendering, the client validates the manifest against a Zod schema defined in packages/types/src/openwork-context.ts. The projection logic merges the fetched manifest with built-in extensions, then applies desktop policies from packages/types/src/den/desktop-policies.ts. These policies—including allowExtensions and allowBuiltInExtensions—prune disallowed extensions from the final list.

Rendering the Extensions Interface

The filtered projection populates three key UI areas: the Extensions settings page, the Marketplace, and the Connect tab. When users navigate to route.settings.extensions, the client invokes window.__openworkControl.execute('extensions.refresh-marketplace') to trigger a fresh fetch. The ee/apps/den-web/app/(den)/dashboard/_components/org-dashboard-shell.tsx component conditionally renders the Extensions navigation item when the user has admin rights, as documented in packages/docs/start-here/add-an-mcp-server.mdx.

Step-by-Step Workflow

The complete lifecycle follows these five stages:

  1. Publish – An admin uploads a manifest (JSON) via the Den UI or API. The backend stores it in the extensions table.
  2. Serve – Den exposes the manifest at /api/v1/extensions/manifest?<orgId>=….
  3. Fetch – The desktop client runs openwork extensions list or calls the MCP search_capabilities RPC. Internally, openwork-bootstrap performs the HTTP fetch.
  4. Validate & Project – The client validates the manifest against the Zod schema (extension kind) and merges it with built-in extensions. Desktop policies filter the results.
  5. Render – The filtered list populates the Extensions UI, allowing users to install, enable, or disable extensions.

Implementation Examples

Fetch and validate a manifest programmatically:

const response = await fetch(manifestUrl);
if (!response.ok) throw new Error(`manifest_fetch_failed: ${response.status}`);
const manifest = await response.json();
validateManifest(manifest); // Zod schema in openwork-context.ts

List extensions via CLI:

openwork extensions list --json

React component consuming projected extensions:

import { useExtensions } from '@/hooks/extensions';

export function ExtensionsPanel() {
  const { extensions, loading } = useExtensions(); // fetches + policy-filters
  if (loading) return <Spinner />;
  return (
    <ul>
      {extensions.map(ext => (
        <li key={ext.id}>
          {ext.name} – {ext.description}
        </li>
      ))}
    </ul>
  );
}

Key Source Files

  • ee/apps/den-web/app/(den)/dashboard/_components/extensions-download-promo.tsx – UI promoting desktop app downloads and manifest links.
  • packages/openwork-bootstrap/bin/openwork.mjs – CLI implementation handling manifest_fetch_failed errors and validation.
  • packages/types/src/openwork-context.ts – Zod schema definitions for the kind field (extensions, panel, voice).
  • ee/apps/den-web/app/(den)/dashboard/_components/org-dashboard-shell.tsx – Dashboard shell injecting the Extensions navigation for admins.
  • packages/docs/start-here/add-an-mcp-server.mdx – Documentation on the Extensions page and client manifest consumption.
  • packages/types/src/den/desktop-policies.ts – Policy definitions controlling extension visibility.

Summary

  • OpenWork Den uses a centralized JSON manifest stored in the extensions table to describe all available plugins and capabilities.
  • The manifest generation phase occurs when admins publish extensions via the Den API or UI.
  • Projection happens through MCP endpoints (search_capabilities) followed by client-side Zod validation and policy filtering (allowExtensions, allowBuiltInExtensions).
  • The desktop client renders only policy-compliant extensions in the Marketplace and Settings interfaces.
  • Key files include the bootstrap CLI (openwork.mjs), type definitions (openwork-context.ts), and dashboard components (org-dashboard-shell.tsx).

Frequently Asked Questions

What format does the OpenWork Den extension manifest use?

The manifest uses JSON format containing fields for ID, name, version, description, capabilities, commands, MCP endpoints, and policy flags (built-in vs local). The client validates this structure against a Zod schema defined in packages/types/src/openwork-context.ts.

How does the desktop client filter which extensions to display?

The client applies desktop policies defined in packages/types/src/den/desktop-policies.ts, specifically checking allowExtensions and allowBuiltInExtensions flags. Only extensions passing these policy checks are projected into the UI.

What happens if the manifest fetch fails?

The bootstrap CLI in packages/openwork-bootstrap/bin/openwork.mjs throws a manifest_fetch_failed error when the HTTP request to /api/v1/extensions/manifest fails or returns invalid data, preventing installation of corrupted extensions.

Can non-admin users access the Extensions marketplace?

No. The org-dashboard-shell.tsx component conditionally renders the Extensions navigation item only when the user has admin rights. However, all users can view projected extensions in the desktop client's Connect tab if policies allow.

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 →