Publishing Marketplace Capabilities in OpenWork: Architecture and Implementation
OpenWork adds marketplace plugins as a fourth capability source in the MCP rail, enabling organization-wide discovery and execution via search_capabilities and execute_capability without requiring local installation.
The different-ai/openwork repository implements a novel approach to publishing marketplace capabilities by extending the Model Context Protocol (MCP) rail with a database-backed plugin source. This architecture allows organizations to distribute tools and skills through centralized marketplaces while maintaining granular access control and zero server-side execution.
The Fourth Capability Source: Adding Marketplace to the MCP Rail
OpenWork integrates the marketplace plugin as a distinct capability source alongside the native REST catalog and External MCP connections. Unlike external connections that require network calls, the marketplace source operates entirely from the database, serving pre-indexed content with no additional latency.
In ee/apps/den-api/src/mcp/agent.ts, the system merges marketplace matches into the standard search results, ensuring capabilities appear in the same shape as External MCP tools. This additive design leaves the existing MCP tool surface unchanged while providing immediate availability of published plugins.
Naming Convention and Capability Identification
The Plugin Namespace Prefix
To avoid collisions and MCP tool-name length limits, OpenWork encodes capability names using a structured prefix scheme. The buildMarketplaceCapabilityName and parseMarketplaceCapabilityName functions in ee/apps/den-api/src/mcp/marketplace-capabilities.ts handle transformations between structured data and string identifiers.
The naming format follows: plugin:<pluginId>:<configObjectId>
For example: plugin:plg_01a2b3c4d5e6:co_09f8e7d6c5b4
This mirrors the existing mcp: naming scheme while ensuring every capability remains uniquely identifiable across the organization.
Searching Marketplace Capabilities
The searchMarketplaceCapabilities function builds searchable lists of active ConfigObjects belonging to plugins. The implementation in ee/apps/den-api/src/mcp/marketplace-capabilities.ts relies on three core operations:
listAccessibleMarketplaceCapabilityReferences– Queries the database for candidate objectsfilterVisibleRows– Applies grant-based visibility filtersscoreMarketplaceRow– Ranks results using the same tokenization engine as the existing search system (defined inee/apps/den-api/src/mcp/search.ts)
Because the source is DB-only, searches execute without network overhead, returning matches interleaved with other capability sources.
Executing Capabilities via Instructional Payloads
When a user invokes execute_capability, the system routes marketplace names to executeMarketplaceCapability in ee/apps/den-api/src/mcp/marketplace-capabilities.ts. This function:
- Parses the capability name to extract plugin and config-object IDs
- Validates grants against the cascading permission model
- Loads the latest config-object version
- Returns an instructional payload containing raw source text, description, and provenance metadata
For command objects, the system substitutes $ARGUMENTS placeholders but never executes code server-side. The payload hands off to the agent or desktop UI for local execution.
// 1️⃣ Build a name that can be searched
const name = buildMarketplaceCapabilityName(pluginId, configObjectId);
// → "plugin:plg_01a2b3c4d5e6:co_09f8e7d6c5b4"
// 2️⃣ Search – returns marketplace matches interleaved with other sources
const matches = await searchCapabilities({ query: "translate", member, organizationId });
// → each match includes `name: "plugin:…"`, `kind`, `plugin`, `summary`, etc.
// 3️⃣ Execute – reads the latest version and returns the instructional payload
const exec = await executeCapability({ name: "plugin:plg_01a2b3c4d5e6:co_09f8e7d6c5b4", member, organizationId });
// exec.result = {
// kind: "skill",
// plugin: "My Awesome Plugin",
// marketplace: "My Marketplace",
// name: "Translate Text",
// description: "Translate a chunk of text",
// provenance: "Content from plugin My Awesome Plugin in your organization's library.",
// content: "... skill source ...",
// status: "ready"
// }
Grant Model and Visibility Cascades
Visibility follows a cascading grant model identical to the plugin system. A member can discover and execute a marketplace capability if they hold a viewer grant on any of the following, checked in order:
- The ConfigObject itself
- The plugin containing the object
- The marketplace housing the plugin
The filterVisibleRows function implements this logic, utilizing resolvePluginArchGrantRole from ee/apps/den-api/src/routes/org/plugin-system/access.ts. Administrators bypass all checks and receive full visibility.
Operational Controls and Status Management
Organization-Level Kill Switches
Organizations can disable the marketplace capability source entirely through the capabilities.mcpConnections metadata flag. When disabled, the gating logic—shared with External MCP connections in ee/apps/den-api/src/mcp/agent.ts—treats the marketplace source as byte-identical to a non-existent source, preventing any discovery or execution.
Capability Status and Hints
Every payload includes status and hint fields to guide the agent or UI. The system reports states through the MarketplaceCapabilityStatus enum and helper functions like basePayload, objectHint, and contentNotSyncedHint. These indicators inform users when capabilities require installation, connection setup, or administrative action, including degraded states such as content_not_synced.
Summary
- Marketplace plugins act as a fourth capability source in the MCP rail, indexed entirely in the database without network overhead.
- Capabilities follow a
plugin:<pluginId>:<configObjectId>naming scheme implemented inmarketplace-capabilities.ts. - Execution returns instructional payloads rather than running code server-side, with support for
$ARGUMENTSsubstitution in command objects. - Visibility follows a cascading grant model checking config objects, plugins, and marketplaces for
viewerpermissions. - Organizations can disable the marketplace source entirely via the
capabilities.mcpConnectionskill-switch.
Frequently Asked Questions
How does OpenWork prevent tool name collisions between different marketplace plugins?
OpenWork uses a structured naming convention prefixed with plugin: that encodes both the plugin ID and config object ID (e.g., plugin:plg_01a2b3c4d5e6:co_09f8e7d6c5b4), ensuring unique identification across the organization while avoiding MCP tool-name length limits.
What happens when a user tries to execute a marketplace capability they don't have permission to view?
The filterVisibleRows function in ee/apps/den-api/src/mcp/marketplace-capabilities.ts enforces visibility through a cascading grant check; if the user lacks a viewer grant on the config object, its parent plugin, or the containing marketplace, the capability is excluded from search results entirely, preventing unauthorized execution attempts.
Does OpenWork execute marketplace plugin code on the server?
No. The executeMarketplaceCapability function returns an instructional payload containing raw source text, description, and provenance metadata; for command objects it substitutes $ARGUMENTS but never executes code server-side, leaving execution to the agent or desktop UI.
How can administrators disable marketplace capabilities organization-wide?
Administrators can set the organization-level metadata capabilities.mcpConnections to disable the marketplace source, which the gating logic in ee/apps/den-api/src/mcp/agent.ts checks alongside External MCP connections, making the marketplace source byte-identical to a non-existent source when disabled.
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 →