How OpenWork MCP Server Integration Works: search_capabilities and execute_capability Tools
OpenWork's MCP server exposes exactly two tools—search_capabilities for discovery and execute_capability for invocation—enabling AI agents to securely browse and call organization-scoped capabilities through a minimal remote endpoint.
The different-ai/openwork repository implements a Model-Context Protocol (MCP) server at https://api.openworklabs.com/mcp/agent that deliberately restricts the agent-facing surface to a strict two-tool contract. This design ensures that external AI agents can only interact with the OpenWork Cloud catalog through a deliberate discovery-then-execution workflow, maintaining security while providing full functional access.
The Minimal Two-Tool Interface
OpenWork operates two distinct MCP endpoints with different tool visibility. The rich /mcp endpoint used by the desktop application registers every OpenAPI-derived tool plus the additive search_capabilities tool. In contrast, the minimal /mcp/agent endpoint—the one external agents connect to—registers only search_capabilities and execute_capability.
This filtering is enforced in the server code where the tools list is explicitly restricted to ["search_capabilities","execute_capability"] according to the source in evals/flows/mcp-search-capabilities.flow.mjs at line 71.
Why Limit the Tool Surface?
By exposing only these two tools, OpenWork prevents agents from directly invoking arbitrary capabilities without first discovering them through the organization's access control layer. The agent must use the two-step pattern: search first, then execute. This is enforced by the UI configuration where the desktop app's Cloud Control connection points at /mcp/agent, which offers no other tool names.
Discovering Capabilities with search_capabilities
The search_capabilities tool serves as the discovery mechanism for the signed-in member's permissions. When an agent calls tools/call with name: "search_capabilities", it submits arguments like { query: "gmail draft", limit: 10 }.
The server searches the organization-scoped catalog, ranks matches, and returns a JSON payload containing each match's name, pathParams, queryParams, and hasBody flags. This response shape is defined in packages/types/src/den/mcp-connection-action.ts, where the retry field is set to the literal "search_capabilities" (lines 15-19), indicating that failed discovery attempts should retry using the same tool.
Executing Capabilities with execute_capability
Once an agent selects a capability from the search results (for example, getOrg), it calls tools/call with name: "execute_capability" and arguments { name: "<match.name>" }.
Internal Routing Through invoke.ts
The server forwards the request to the unchanged invoke.ts implementation, which resolves the underlying OpenAPI operation and returns the real data. This guarantees that /mcp/agent executions behave identically to calls made through the full /mcp catalog, as both paths route through the same internal invocation logic.
Error Handling for Invalid Capabilities
If an unknown capability name is supplied to execute_capability, the server responds with a structured error object where the error field equals "unknown_capability". This validation occurs before any execution attempt, preventing unauthorized access to undefined operations (as shown in evals/flows/mcp-search-capabilities.flow.mjs at step 13).
Step-by-Step Integration Workflow
The end-to-end flow demonstrates how these tools work together to retrieve live data. According to the evaluation flow in evals/flows/mcp-search-capabilities.flow.mjs (steps 6-8), the sequence is: search_capabilities discovers the capability, then execute_capability retrieves the org ID and name using the exact capability name.
Configuring the MCP Client
To connect an MCP-compatible client like OpenCode, add the remote server configuration:
# Add the MCP entry to opencode.json
cat >> opencode.json <<'EOF'
{
"mcp": {
"openwork": {
"type": "remote",
"enabled": true,
"url": "https://api.openworklabs.com/mcp/agent",
"oauth": {}
}
}
}
EOF
Authenticate to bind your organization:
opencode mcp auth openwork
This opens a browser for sign-in and organization selection, pinning the chosen org into the access token.
Example JSON-RPC Calls
The LLM agent internally translates plain-English prompts into these structured calls. First, the discovery request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_capabilities",
"arguments": { "query": "gmail draft", "limit": 5 }
}
}
Sample response showing the call shape hints:
{
"content": [
{
"text": "{\"matches\":[{\"name\":\"postCapabilitiesGoogleWorkspaceGmailDrafts\",\"pathParams\":[],\"queryParams\":[],\"hasBody\":true}]}"
}
]
}
Then, the execution request using the exact capability name:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "execute_capability",
"arguments": {
"name": "postCapabilitiesGoogleWorkspaceGmailDrafts",
"body": {
"to": "bob@example.com",
"subject": "Hello",
"body": "Hi!"
}
}
}
}
Successful execution returns the actual data:
{
"content": [{ "text": "{\"draftId\":\"DRAFT_12345\"}" }]
}
Summary
- Two-tool contract: The
/mcp/agentendpoint deliberately exposes onlysearch_capabilitiesandexecute_capability, enforced by server-side filtering inmcp-search-capabilities.flow.mjs. - Discovery phase:
search_capabilitiessearches the organization-scoped catalog and returns ranked matches with parameter hints (pathParams, queryParams, hasBody). - Execution phase:
execute_capabilityroutes throughinvoke.tsto invoke the underlying OpenAPI operation using the exact capability name discovered previously. - Error safety: Unknown capability names return
"unknown_capability"errors before execution. - Client configuration: MCP clients like OpenCode connect to
https://api.openworklabs.com/mcp/agentvia OAuth, after which the LLM automatically handles the two-step search-then-execute pattern.
Frequently Asked Questions
What is the difference between OpenWork's /mcp and /mcp/agent endpoints?
The /mcp endpoint is the rich interface used by the desktop application that registers every OpenAPI-derived tool plus search_capabilities. The /mcp/agent endpoint is the minimal external interface that exposes only search_capabilities and execute_capability, forcing AI agents through a controlled discovery workflow.
Can I call execute_capability without first calling search_capabilities?
Technically yes, but you must know the exact capability name beforehand. The system validates the name against the catalog; if it doesn't exist, it returns an "unknown_capability" error. The intended workflow requires search_capabilities to discover valid names, as the minimal endpoint provides no other way to browse available operations.
Where is the capability execution actually handled in the codebase?
All capability executions route through the invoke.ts implementation, regardless of whether they originate from the rich /mcp endpoint or the minimal /mcp/agent endpoint. This ensures consistent behavior and authorization checks across all entry points.
How does the retry field work in the connection action schema?
In packages/types/src/den/mcp-connection-action.ts, the schema defines a retry field set to the literal "search_capabilities". This instructs the system that if a discovery operation fails, it should retry using the same search_capabilities tool, maintaining the two-step contract even during error recovery.
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 →