MCP Server Exposure & Workloads
Technical reference. This page is for integrations, advanced configuration, or platform operations. For portal tasks, start with the user guide.
Orqestra can expose any flow as an MCP tool, making it callable by external AI agents. It also provides workload runtime interfaces for non-technical users to interact with governed flows directly.
Calling an external MCP server from a workload
External MCP calls use the fixed mcp_client acting identity or the
server-owned mcp_client_advisory service identity. These are distinct
identities, not a caller-facing authentication switch. Acting calls use the
governed delegated path; advisory calls require the independently installed
and release-bound connector plus its mcp_server target and auth_token
secret slot. Package installation is scoped to a fresh workspace install and
never silently binds a release or chooses a connection.
Task inputs contain the target and tool selection only. auth_token and
arbitrary request headers are not accepted as callable MCP inputs; the
runtime injects an approved connector secret only after the server-owned
target, release, and connection pin agree. Readback exposes bounded
credential-kind/correlation data and canonical decimal identifiers, never
token material. external_as remains fail-closed pending the separately
tracked enterprise integration.
MCP Server Exposure
The Model Context Protocol (MCP) allows AI agents to discover and invoke tools. Orqestra acts as an MCP server, exposing your governed flows as tools that external agents can call.
Install-vs-Binding For Package-Shipped MCP Servers
An mcp_server asset can be hand-authored directly (below), or it can ship as
a package-local asset inside an official or community plugin package and
installed through the package lifecycle (see
Plugins & Connectors). Either way, installing an
mcp_server asset does not make it usable by a release — an installed
package asset is only Available (materialized, runtime-scoped), not Bound.
Explicitly bind it to a release role before it is exposed:
orqestractl plugin bind <release_id> \
"pkg:<package_name>@<version>/mcp_server/<package_local_slug>@<asset_version>" \
mcp_server \
--workspace <workspace_id>See Resolving And Binding Installed Assets for the package-ref grammar and the fail-closed resolve/bind behavior.
How It Works
- Register an
mcp_serverasset that defines which flows are exposed - External agents discover available tools via the MCP protocol
- When an agent calls a tool, Orqestra executes the corresponding flow with full governance (policy evaluation, evidence capture, guardrails)
- The result is returned to the calling agent
MCP Server Configuration
Create an mcp_server asset to define the exposure:
{
"server_name": "orqestra-tools",
"description": "Governed AI tools powered by Orqestra",
"tools": [
{
"name": "knowledge_search",
"description": "Search the company knowledge base with governed RAG",
"flow_slug": "knowledge-qa",
"input_schema": {
"type": "object",
"required": ["query"],
"properties": {
"query": { "type": "string", "description": "The search query" }
}
}
},
{
"name": "classify_ticket",
"description": "Classify a support ticket by urgency",
"flow_slug": "ticket-classifier",
"input_schema": {
"type": "object",
"required": ["ticket_text"],
"properties": {
"ticket_text": { "type": "string" }
}
}
}
]
}Key Benefits
| Benefit | Description |
|---|---|
| Governed tool calls | Every invocation goes through Orqestra’s policy evaluation and evidence capture |
| Reuse existing flows | No separate implementation needed — any flow becomes a tool |
| Discoverability | Tools appear in MCP catalogs (Azure Foundry Tools, Vertex AI API Hub, etc.) |
| Audit trail | Full execution trace for every external tool invocation |
Pinning Tool Schemas And Reauthorizing Drift
A remote MCP server can change the tools it advertises, and their schemas, at any time — Orqestra does not control it. Pinning turns that from an invisible change into a governed one.
The operator loop
Operator surfaces live under Connect → External systems → MCP servers. Reading them needs
asset.view; approving or revoking needs tool_permission.manage. Running
discovery needs both tool_permission.manage and connection.read.
- Discover. Take a snapshot of what the server currently advertises. Snapshots are immutable and append-only, so the list is an audit trail rather than a current-state view.
- Review. Inspect each tool and its schema in the snapshot.
- Approve. Authorize either the
complete_inventoryor aselected_toolssubset drawn from that snapshot, with a written reason. The confirmation restates target, version, snapshot, tool count and reason before anything is written. - Watch. Live observations record what the runtime actually saw before each call, and whether it matched the pin.
What happens at call time
Before a workload calls a remote MCP tool, the runtime lists the server’s live inventory and compares it to the approved pin. The comparison result is committed as an observation before any tool call goes out. If the live inventory has drifted from what was approved, the call is denied with no outbound request.
Denials are recorded, not silent. The observation carries the closed reason, the expected and observed digests, and the credential-generation correlation — never provider content, arguments, headers or credentials.
Reauthorizing after drift
Reauthorization is deliberately not a button that re-blesses the current state. It is new discovery followed by a new approval: you take a fresh snapshot of what the server advertises now, read it, and approve that. The previous approval is retained as superseded rather than rewritten, so the history shows what was authorized when.
Rediscovering while an approval is already active is a reauthorization attempt, so the portal asks for confirmation before it runs — a single accidental click on Run discovery never disturbs a live approval basis by itself.
Revocation works the same way — the approval row is marked revoked, never deleted.
Reading observations from the CLI
# Snapshots and approval history for one MCP server asset version
orqestractl mcp-tool-schema snapshots <asset-id> <asset-version-id>
orqestractl mcp-tool-schema approvals <asset-id> <asset-version-id>
# Live observations, optionally narrowed
orqestractl mcp-tool-schema observations --state denied
orqestractl mcp-tool-schema observations --execution-id <execution-id>These commands are read-only by design. Approving an inventory is an operator decision that belongs with the confirmation step the portal shows; a scripted approve would skip it.
External-AS OAuth Registration (DCR)
Some remote MCP targets require Orqestra to authenticate as a registered
OAuth client of the target’s own authorization server (AS), rather than
presenting a static bearer token. For those targets, an operator opts a
mcp_server asset into guarded RFC 7591 Dynamic Client Registration (DCR)
and manages the resulting client credential’s lifecycle through the
control plane.
Concepts
| Concept | Description |
|---|---|
dcr_enabled | Explicit operator opt-in on the mcp_server asset. Omitted or false means discovery performs no DCR registration. |
transport_auth | Must be oauth for a target to be eligible for registration. |
credential_source | Consumption-side choice: broker (default) uses the existing delegated-identity broker path, unaffected by registration. external_as consumes THIS target’s own DCR-registered client_credentials access token instead, engaged only when an active, usable registration exists — otherwise the target is denied (no silent fallback to the broker). |
| Registration | The persisted outcome of a DCR call: a non-secret client_id plus a Vault credential_ref (the secret’s NAME, never its value). |
| Token acquisition | A separate, operator-gated action that exchanges the registered credential for a client_credentials access token (RFC 6749 §4.4). Scoped to client_credentials only; Orqestra does not expose an authorization-code/PKCE browser flow. |
Lifecycle
# 1. Register — one-time RFC 7591 DCR call against the target's own AS.
curl -X POST "http://localhost:8000/v1/mcp-oauth-registrations/?workspace_id=workspace-123" \
-H "Content-Type: application/json" \
-d '{
"mcp_server_asset_id": "asset-id",
"redirect_uris": ["https://callback.orqestra.example/oauth/mcp"]
}'
# 2. Acquire a client_credentials access token for the registration.
curl -X POST "http://localhost:8000/v1/mcp-oauth-registrations/{registration_id}/token?workspace_id=workspace-123"
# 3. Refresh — re-acquires only if the current token is expired/near-expiry;
# a no-op otherwise (client_credentials has no refresh_token, RFC 6749 §4.4).
curl -X POST "http://localhost:8000/v1/mcp-oauth-registrations/{registration_id}/refresh?workspace_id=workspace-123"
# 4. Rotate — re-runs DCR and supersedes the Vault-stored client secret,
# keeping the same registration_id.
curl -X POST "http://localhost:8000/v1/mcp-oauth-registrations/{registration_id}/rotate?workspace_id=workspace-123" \
-H "Content-Type: application/json" \
-d '{"redirect_uris": ["https://callback.orqestra.example/oauth/mcp"]}'
# 5. Revoke — deletes the Vault-stored secret(s), marks the registration
# revoked, and best-effort revokes the access token upstream (RFC 7009).
# Local revocation always completes even if the upstream call fails.
curl -X POST "http://localhost:8000/v1/mcp-oauth-registrations/{registration_id}/revoke?workspace_id=workspace-123"The redirect URIs must resolve against the Orqestra OAuth-callback allowlist
(ORQESTRA_OAUTH_CALLBACK_HOSTS), a boundary distinct from the remote-MCP
egress allowlist. The raw client secret and access token are never returned
in any response, logged, or written to audit — only the Vault
credential_ref/token_credential_ref (secret names) and token_expires_at
are exposed.
Permissions
| Operation | Permission |
|---|---|
| Read a registration | mcp_oauth_registration.read |
| Register, acquire/refresh token, rotate, revoke | mcp_oauth_registration.manage |
Python SDK
from orqestra_sdk import OrqestraClient
async with OrqestraClient("http://localhost:8000", workspace_id="workspace-123") as client:
registration = await client.mcp_oauth_registrations.register(
mcp_server_asset_id="asset-id",
redirect_uris=["https://callback.orqestra.example/oauth/mcp"],
workspace_id="workspace-123",
)
await client.mcp_oauth_registrations.acquire_token(
registration["registration_id"], workspace_id="workspace-123"
)
await client.mcp_oauth_registrations.refresh_token(
registration["registration_id"], workspace_id="workspace-123"
)
await client.mcp_oauth_registrations.rotate(
registration["registration_id"],
redirect_uris=["https://callback.orqestra.example/oauth/mcp"],
workspace_id="workspace-123",
)
await client.mcp_oauth_registrations.revoke(
registration["registration_id"], workspace_id="workspace-123"
)CLI
orqestractl mcp-oauth-registration register \
--mcp-server-asset-id asset-id \
--redirect-uri https://callback.orqestra.example/oauth/mcp \
--workspace-id workspace-123
orqestractl mcp-oauth-registration token <registration_id> --workspace-id workspace-123
orqestractl mcp-oauth-registration refresh <registration_id> --workspace-id workspace-123
orqestractl mcp-oauth-registration rotate <registration_id> \
--redirect-uri https://callback.orqestra.example/oauth/mcp \
--workspace-id workspace-123
orqestractl mcp-oauth-registration revoke <registration_id> --workspace-id workspace-123Reading Permission Evidence
The read-only list_permission_evidence MCP tool returns one bounded,
workspace-scoped page of redacted permission decisions. Call it with
workspace_id; pass its opaque next_cursor as cursor to continue. Each
page is limited to 100 records and requires policy.view in that workspace.
The tool exposes recorded outcome and reason codes, policy/profile/evaluator
revisions, freshness, lineage, and any result acknowledgement. Missing records
or an absent acknowledgement remain unknown; neither means the operation was
never attempted. The reader does not return source content, credentials, or
source ACL grants.
Enterprise Outbound Authorization Conformance
For a target whose credential_source is external_as, Orqestra enforces a
consolidated enterprise conformance contract: six additional posture fields,
each explicit and independently checked by the runtime admission gate before
discovery or a tool call reaches the target. Every field is required and
denies admission (with its own stable reason code) when absent or unsupported
— the pre-existing broker credential-source path is a separate governance
axis and does not need (or accept) these fields.
| Field | Required value | What it declares |
|---|---|---|
audience_resource | exact_endpoint | The credential is bound to the exact resolved call/discovery endpoint, never a bare host. |
issuer_validation | discovery_verified | The target’s authorization-server issuer was resolved and https-validated via the OAuth discovery-metadata chain. |
scope_capability | registration_scoped | The credential’s authority is bounded by that target’s own DCR client registration, never a broader static scope. |
refresh_rotation | registration_managed | The registration’s :refresh/:rotate actions (above) manage the credential’s freshness. |
revocation | registration_revocable | The registration’s status and :revoke action govern revocation. |
credential_provenance | vault_secret_reference | The credential material is referenced by a governed Vault credential_ref (the secret’s NAME), never raw material in code/config. |
{
"url": "https://mcp.partner.example.com",
"transport_auth": "oauth",
"capability_class": "read_only",
"credential_source": "external_as",
"audience_resource": "exact_endpoint",
"issuer_validation": "discovery_verified",
"scope_capability": "registration_scoped",
"refresh_rotation": "registration_managed",
"revocation": "registration_revocable",
"credential_provenance": "vault_secret_reference"
}The bounded value sets are contract-owned (scripts/manifests/mcp-authorization-conformance.toml,
mirrored in mcp_authorization_conformance_value_sets.schema.json), versioned,
and lockstep-gated: a target declaring a value the contract does not enumerate
fails closed, never assumed compatible. Denial evidence
(v1.governance.mcp_target_admission_decided) records the credential
category (broker/external_as) and the closed gap-reason codes, never
credential material or a token.
Workload Runtime Interfaces
For non-technical users who need to interact with AI capabilities without understanding flows, Orqestra provides a workload runtime surface.
Workload Interface Configuration
Workloads with the interface_config field define a UI presentation layer:
{
"interface_config": {
"title": "Knowledge Assistant",
"description": "Ask questions about company policies and procedures",
"interface": "chat",
"branding": {
"icon": "brain",
"color": "#2ea97a"
},
"input_fields": [
{
"name": "query",
"type": "text",
"label": "Ask a question",
"placeholder": "What is our refund policy?"
}
]
}
}Apps
The portal provides an Apps page where users browse and launch available workload interfaces:
# List available runtime workloads with their configurations
curl GET /v1/workloads/runtime-enabledResponse includes each workload’s display name, description, interface type, and status, enabling a self-service experience for consumers.
Interface Types
| Interface | Description |
|---|---|
chat | Conversational interface with message history |
api | Programmatic interface for system-to-system calls |
form | Structured input form with defined fields |
API Reference
MCP Server Assets
# Create an MCP server asset
curl -X POST /v1/assets \
-d '{
"slug": "company-tools",
"asset_kind": "mcp_server",
"owner_ref": "team:platform"
}'
# Create a version with tool definitions
curl -X POST /v1/assets/{asset_id}/versions \
-d '{
"version_label": "v1",
"content": {
"server_name": "company-tools",
"tools": [...]
}
}'Workload Gallery
# List workloads with runtime interface configs
curl GET /v1/workloads/runtime-enabledBest Practices
Write clear tool descriptions. External agents use the
descriptionfield to decide when to call your tool. Be specific about what the tool does and what inputs it expects.
Define strict input schemas. Input validation prevents malformed requests from reaching your flows. Use JSON Schema constraints to enforce required fields and types.
Apply guardrails to MCP-exposed flows. External agents may send unexpected content. Ensure flows exposed via MCP have guardrails configured for input validation and content safety.
Monitor MCP tool usage. Track invocation patterns via the observability dashboard to understand how external agents use your tools and identify optimization opportunities.