How OpenWork MCP Gateway search_capabilities and execute_capability Work

The OpenWork MCP gateway exposes two JSON-RPC tools—search_capabilities for querying the capability catalog and execute_capability for invoking specific skills—that agents access via the /mcp/agent endpoint using short-lived JWT tokens.

The different-ai/openwork repository implements a Model Control Plane (MCP) gateway in the ee/apps/den-api server, enabling AI agents to programmatically discover and execute capabilities. The gateway's search_capabilities and execute_capability tools provide authenticated, permission-scoped access to skills, apps, and integrations stored in the underlying database, with request validation handled by Zod schemas defined in the shared types package.

Understanding the OpenWork MCP Gateway Architecture

The MCP gateway operates as a stateless JSON-RPC server that brokers interactions between AI agents and the OpenWork capability ecosystem. Agents interact with two primary tools exposed through the /mcp/agent endpoint:

  • search_capabilities – Queries the capability catalog using full-text search with optional filters for type (e.g., "skills", "apps") and result limits.
  • execute_capability – Invokes a specific capability by its scriptPath identifier, executing the underlying implementation with provided arguments.

Both tools require a valid MCP token (JWT) in the Authorization: Bearer header. The gateway validates the token, checks organization-level permissions, and routes requests to the appropriate service layer in ee/apps/den-api.

How search_capabilities Works

Request Flow and Validation

When an agent calls search_capabilities, the gateway first validates the request payload against the Zod schema defined in packages/types/src/den/mcp-connection-action.ts. The schema enforces parameters including query (string), limit (number, optional), and type (string, optional).

The validated request flows to CapabilityService.search in ee/apps/den-api/src/services/capability.ts. This service constructs a full-text database query against the Capability table, applying filters that respect the calling identity's organizational access grants. The service returns paginated results containing metadata fields: id, name, description, and scriptPath.

Implementation Example

// Agent-side invocation pattern from evals/specs/workflows.e2e.test.ts
const searchResult = await callAgentTool(
  den.ref.apiUrl,
  adminMcpToken,
  "search_capabilities",
  { 
    query: "list workers", 
    limit: 20, 
    type: "skills" 
  }
);

const matches = searchResult.payload.matches;
// Returns: [{ id: "...", name: "List Workers", scriptPath: "openwork-cloud/skills/list-workers", ... }]

The gateway returns matches as an array of capability descriptors, allowing agents to programmatically select appropriate tools for subsequent execution.

How execute_capability Works

Execution Flow

The execute_capability tool transforms a capability identifier into an actual function invocation. The gateway accepts a scriptPath string (obtained from search_capabilities) and an input object containing capability-specific arguments.

The route handler in ee/apps/den-api/src/routes/mcp.ts delegates to the execution layer. The system first validates that the caller's organization has permission to access the requested scriptPath, then loads the capability implementation. For concrete execution logic, the gateway utilizes ee/apps/den-api/src/services/capability-executor.ts, which resolves the script reference and forwards the invocation to the underlying runtime.

Security and Error Handling

The gateway enforces strict access control before execution. If the scriptPath does not exist or the caller lacks permission, the gateway returns a JSON-RPC error object with appropriate error codes. Successful invocations stream the execution result back to the agent as the JSON-RPC response payload.

// Executing a discovered capability
const execResult = await callAgentTool(
  den.ref.apiUrl,
  adminMcpToken,
  "execute_capability",
  {
    scriptPath: "openwork-cloud/skills/list-workers",
    input: { filter: "active", maxResults: 100 }
  }
);

console.log(execResult.payload); // Execution output from the capability

End-to-End Usage Pattern

Agents typically chain these tools to discover and act upon capabilities dynamically. The following pattern from evals/runner/journeys/mcp.ts demonstrates the complete workflow:

// 1. Discover capabilities
const skillSearch = await callAgentTool(
  den.ref.apiUrl,
  adminMcpToken,
  "search_capabilities",
  { query: "create skill", limit: 5 }
);

const targetSkill = skillSearch.payload.matches.find(
  m => m.name.includes("create_skill")
);

// 2. Execute selected capability
if (targetSkill) {
  const createResult = await callAgentTool(
    den.ref.apiUrl,
    adminMcpToken,
    "execute_capability",
    { 
      scriptPath: targetSkill.scriptPath, 
      input: { name: "data-processor", description: "Process CSV files" } 
    }
  );
  return createResult.payload;
}

This pattern enables agents to operate within the OpenWork ecosystem without hardcoding capability endpoints, adapting dynamically to available tools.

Key Source Files and Architecture

The MCP gateway implementation spans several critical files in the different-ai/openwork repository:

Summary

  • search_capabilities enables agents to query the OpenWork capability catalog with full-text search, returning metadata including scriptPath identifiers scoped to the caller's organizational permissions.
  • execute_capability invokes specific capabilities by scriptPath, executing the underlying implementation after validating access rights and streaming results back to the agent.
  • Both tools are exposed through the stateless /mcp/agent JSON-RPC endpoint in the den-api server, utilizing Zod schemas for input validation.
  • The gateway delegates search operations to CapabilityService in ee/apps/den-api/src/services/capability.ts and execution to the service layer in ee/apps/den-api/src/services/capability-executor.ts.

Frequently Asked Questions

What is the difference between search_capabilities and execute_capability in OpenWork?

search_capabilities is a read-only catalog query tool that returns metadata about available capabilities, while execute_capability is an action tool that invokes the actual implementation of a specific capability using its scriptPath identifier. Agents use search to discover what actions they can perform, then execute to run them.

How does the OpenWork MCP gateway authenticate tool requests?

The gateway requires a short-lived MCP token (JWT) passed in the Authorization: Bearer header. According to the source code in ee/apps/den-api, the gateway validates this token and extracts organizational claims to enforce permission checks before processing search_capabilities or execute_capability calls.

What data structure does search_capabilities return?

The tool returns a JSON-RPC payload containing a matches array, where each element includes fields such as id, name, description, and scriptPath. These descriptors originate from the Capability table via CapabilityService.search and are filtered based on the caller's organizational access rights.

Where is the capability execution logic implemented?

The execution logic resides in ee/apps/den-api/src/services/capability-executor.ts, which is called by the gateway route handler after permission validation. This service resolves the scriptPath provided in the execute_capability request and forwards the invocation to the appropriate runtime environment or remote integration.

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 →