# How Marketplace Capabilities Are Discovered in OpenWork

> Discover OpenWork marketplace capabilities using the search_capabilities MCP tool. Learn how it queries the Den database to find authorized plugins and skills.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: how-to-guide
- Published: 2026-08-21

---

**Marketplace capabilities in OpenWork are discovered through the `search_capabilities` MCP tool, which authenticates the caller via MCP token, queries the Den database for authorized marketplace plugins and skills, and returns a normalized capability catalog.**

The `different-ai/openwork` repository implements a multi-layered discovery pipeline that connects AI agents to marketplace resources. Understanding how **Marketplace capabilities are discovered** requires examining the database schema, business logic, and API endpoint that orchestrate this process.

## MCP search_capabilities Architecture

### Database Schema in plugin-arch.ts

The discovery process originates in [`dev/ee/packages/den-db/src/schema/sharables/plugin-arch.ts`](https://github.com/different-ai/openwork/blob/main/dev/ee/packages/den-db/src/schema/sharables/plugin-arch.ts), which defines the three core tables governing marketplace access:

- **`Marketplace`**: Stores marketplace metadata and configuration
- **`MarketplacePlugin`**: Links plugins to specific marketplaces
- **`MarketplaceAccessGrant`**: Controls which organization members can access specific marketplace resources

These tables establish the relationships required for capability discovery. When an agent requests resources, the system performs joins across these tables to enforce authorization at the database level.

### Business Logic in cloud-plugins.ts

The [`dev/evals/packages/behaviors/src/cloud-plugins.ts`](https://github.com/different-ai/openwork/blob/main/dev/evals/packages/behaviors/src/cloud-plugins.ts) file contains the core functions that implement marketplace discovery logic. According to the OpenWork source code, key operations include:

- **`cloud.listMarketplaces()`**: Retrieves all marketplaces accessible to the current session
- **`cloud.readResolvedMarketplace()`**: Fetches a specific marketplace with resolved arrays of `pluginNames` and `skillNames`
- **`gatherMarketplaceCapabilities()`**: Assembles capability objects from database records while filtering by access grants
- **`assignPluginToMarketplace()`**: Associates plugins with marketplaces (admin function)
- **`createMarketplace()`**: Provisions new marketplace instances

These functions enforce row-level security by checking `MarketplaceAccessGrant` entries before returning data.

### Route Handler in mcp.ts

The [`dev/ee/apps/den-api/src/routes/mcp.ts`](https://github.com/different-ai/openwork/blob/main/dev/ee/apps/den-api/src/routes/mcp.ts) file implements the Model Context Protocol (MCP) HTTP endpoint that exposes the `search_capabilities` tool. This route handler:

1. Validates MCP tokens to authenticate the requesting agent
2. Invokes `gatherMarketplaceCapabilities()` to retrieve authorized resources
3. Merges marketplace capabilities with core OpenWork system capabilities
4. Returns the structured catalog as a JSON response

## Step-by-Step Discovery Flow

The **Marketplace capabilities discovery** process follows this execution path:

1. **Authentication**: The agent presents an MCP token to the `/mcp/agent` endpoint in `den-api`
2. **Authorization Check**: The system validates the token and retrieves the member's organization scopes from the session
3. **Database Query**: The server queries `Marketplace`, `MarketplacePlugin`, and `MarketplaceAccessGrant` tables using the schema defined in [`plugin-arch.ts`](https://github.com/different-ai/openwork/blob/main/plugin-arch.ts)
4. **Capability Assembly**: The `gatherMarketplaceCapabilities()` function in [`cloud-plugins.ts`](https://github.com/different-ai/openwork/blob/main/cloud-plugins.ts) constructs capability objects containing `pluginName`, `skillName`, `marketplaceId`, and UI metadata
5. **Catalog Construction**: The MCP route handler merges marketplace capabilities with platform capabilities
6. **Response Delivery**: The endpoint returns a JSON payload that the client renders as Marketplace Plugin cards

## Practical Code Examples

### Querying Marketplace Capabilities from an Agent

```typescript
// Example: Discovering available marketplace plugins
const result = await callTool(
  den.ref.apiUrl,                     // Den base URL
  mcpToken,                           // MCP authentication token
  "search_capabilities",
  { query: "marketplace", limit: 20 } // Optional filtering parameters
);

const matches = result.payload.matches; // Array of capability objects
console.log(matches.map(m => m.name));  // ["My Awesome Plugin", ...]

```

The returned capability objects match this structure:

```json
{
  "id": "plugin-abc123",
  "name": "My Awesome Plugin",
  "skillName": "my_awesome_skill",
  "marketplaceId": "mk-001",
  "type": "plugin"
}

```

### Reading Resolved Marketplace Data

```typescript
import { readResolvedMarketplace } from "dev/evals/packages/behaviors/src/cloud-plugins";

const marketplace = await readResolvedMarketplace(memberSession, "mk-001");
console.log(marketplace.pluginNames); // ["My Awesome Plugin", ...]
console.log(marketplace.skillNames);  // ["my_awesome_skill", ...]

```

### Admin: Creating and Populating Marketplaces

```typescript
import { assignPluginToMarketplace, createMarketplace } from "dev/evals/packages/behaviors/src/cloud-plugins";

// Create a new marketplace
const mk = await createMarketplace(adminSession, { name: "Team Marketplace" });

// Assign a plugin to the marketplace
await assignPluginToMarketplace(adminSession, mk.id, pluginId);

```

## Key Source Files

- **[`dev/ee/packages/den-db/src/schema/sharables/plugin-arch.ts`](https://github.com/different-ai/openwork/blob/main/dev/ee/packages/den-db/src/schema/sharables/plugin-arch.ts)**: Defines the `Marketplace`, `MarketplacePlugin`, and `MarketplaceAccessGrant` database schema
- **[`dev/evals/packages/behaviors/src/cloud-plugins.ts`](https://github.com/different-ai/openwork/blob/main/dev/evals/packages/behaviors/src/cloud-plugins.ts)**: Implements `listMarketplaces`, `readResolvedMarketplace`, and capability gathering logic
- **[`dev/ee/apps/den-api/src/routes/mcp.ts`](https://github.com/different-ai/openwork/blob/main/dev/ee/apps/den-api/src/routes/mcp.ts)**: MCP route handler serving the `search_capabilities` endpoint
- **[`dev/evals/specs/self-host-onboarding.e2e.test.ts`](https://github.com/different-ai/openwork/blob/main/dev/evals/specs/self-host-onboarding.e2e.test.ts)**: End-to-end test demonstrating the discovery flow
- **[`dev/evals/specs/den-sidebar-ia.e2e.test.ts`](https://github.com/different-ai/openwork/blob/main/dev/evals/specs/den-sidebar-ia.e2e.test.ts)**: UI test validating marketplace card rendering after discovery

## Summary

- **Marketplace capabilities** are discovered via the `search_capabilities` MCP tool exposed in [`den-api/src/routes/mcp.ts`](https://github.com/different-ai/openwork/blob/main/den-api/src/routes/mcp.ts)
- The **Den database schema** in [`plugin-arch.ts`](https://github.com/different-ai/openwork/blob/main/plugin-arch.ts) models marketplaces, plugins, and access grants for secure querying
- **Business logic** in [`cloud-plugins.ts`](https://github.com/different-ai/openwork/blob/main/cloud-plugins.ts) enforces authorization through `MarketplaceAccessGrant` checks
- **Authentication** requires valid MCP tokens, which scope all results to authorized resources only
- The discovery flow merges marketplace plugins and skills with core platform capabilities for unified consumption

## Frequently Asked Questions

### How does OpenWork secure Marketplace capability discovery?

OpenWork secures discovery through **MCP token authentication** and database-level access control. The `MarketplaceAccessGrant` table in [`plugin-arch.ts`](https://github.com/different-ai/openwork/blob/main/plugin-arch.ts) defines which organization members can view specific marketplace resources. When `search_capabilities` is called, the `gatherMarketplaceCapabilities()` function joins this table with `Marketplace` and `MarketplacePlugin` to filter results, ensuring agents only receive capabilities they are explicitly authorized to use.

### What is the difference between `listMarketplaces` and `readResolvedMarketplace`?

The `cloud.listMarketplaces()` function returns a catalog of marketplace summaries accessible to the session, optimized for discovery UIs. In contrast, `cloud.readResolvedMarketplace()` fetches complete details for a specific marketplace ID, including fully resolved arrays of `pluginNames` and `skillNames`. Use list operations for browsing and resolved reads for execution contexts requiring full configuration data.

### Can agents filter capabilities when calling `search_capabilities`?

Yes, the `search_capabilities` endpoint accepts optional parameters including query strings and limit values. Agents can pass `{ query: "specific-term", limit: 10 }` to filter the capability catalog. However, the backend in [`cloud-plugins.ts`](https://github.com/different-ai/openwork/blob/main/cloud-plugins.ts) always enforces access grant restrictions regardless of client-side filters, ensuring security boundaries remain intact.

### Where is the database schema for marketplace plugins defined?

The database schema resides in [`dev/ee/packages/den-db/src/schema/sharables/plugin-arch.ts`](https://github.com/different-ai/openwork/blob/main/dev/ee/packages/den-db/src/schema/sharables/plugin-arch.ts). This file defines the `Marketplace`, `MarketplacePlugin`, and `MarketplaceAccessGrant` tables using the Den database ORM. These definitions establish the relationships required for the discovery system to join marketplace resources with user permissions and drive the `search_capabilities` response.