Skip to main content

MCP Server API

Table of Contents

Top

upsquad/mcpserver/v1/credential.proto

DeleteMCPServerCredentialRequest

DeleteMCPServerCredentialRequest identifies the credential to remove at a given scope. The tenant is taken from the auth context.

FieldTypeLabelDescription
registry_idstringregistry_id is the mcp_servers registry id the credential belongs to.
credential_typestringcredential_type selects which stored credential to remove ("bearer_token"
unit_idstringunit_id scopes the delete to a team, identically to the Set request.
agent_idstringagent_id scopes the delete to an agent (mutually exclusive with unit_id; both absent ⇒ org-level _default), identically to the Set request.

DeleteMCPServerCredentialResponse

DeleteMCPServerCredentialResponse confirms the removal WITHOUT returning any secret material.

FieldTypeLabelDescription
registry_idstringregistry_id echoes the server the credential was removed for.
credential_typestringcredential_type echoes the removed credential kind.
vault_refstringvault_ref is the scope-qualified ref that was targeted.
deletedbooldeleted is true when a row was removed, false when none existed (idempotent).
deleted_atgoogle.protobuf.Timestampdeleted_at is the server time the delete was processed.

ListMCPServerCredentialsRequest

ListMCPServerCredentialsRequest enumerates a single team's stored MCP credentials. The tenant (org) is taken from the auth context; only the team is carried here.

FieldTypeLabelDescription
unit_idstringunit_id is the team (org_unit of unit_type 'team') whose shared credentials are listed. Required. MUST be a team the caller's tenant owns (IDOR-guarded); a cross-tenant or unknown id is rejected NotFound.

ListMCPServerCredentialsResponse

ListMCPServerCredentialsResponse returns the team's masked credential summaries.

FieldTypeLabelDescription
credentialsMCPServerCredentialSummaryrepeatedcredentials is the masked summary per stored (server, credential_type), oldest-first. Empty when the team has no stored credentials.

MCPServerCredentialSummary

MCPServerCredentialSummary is one masked credential row. It NEVER carries the plaintext secret — only a masked hint.

FieldTypeLabelDescription
registry_idstringregistry_id is the mcp_servers id the credential is bound to (parsed from the stored vault provider name mcp_<type>_<registry_id>).
server_namestringserver_name is the bound server's display name, or empty when the server was deregistered (the credential row still surfaces so the UI can offer cleanup).
credential_typestringcredential_type is the stored credential kind: "bearer_token"
masked_hintstringmasked_hint is a UI-safe fingerprint exposing only the last 4 chars (e.g. "••••AB12"). It is derived inside Postgres and is NEVER the plaintext.
created_atgoogle.protobuf.Timestampcreated_at is when the credential was first stored.
last_rotated_atgoogle.protobuf.Timestamplast_rotated_at is when the credential was last (re)written.

SetMCPServerCredentialRequest

SetMCPServerCredentialRequest carries the target server + the raw secret. The tenant is taken from the auth context (never from the request body).

FieldTypeLabelDescription
registry_idstringregistry_id is the mcp_servers registry id the credential belongs to. It is part of the vault key so a server's credential is isolated per server.
credential_typestringcredential_type selects which upstream credential is being stored: - "bearer_token" — a static Bearer token (bearer upstream-auth mode) - "oauth_client_secret" — the gateway's OAuth client_secret (oauth2 mode) Validated server-side; any other value is rejected.
secretstringsecret is the raw credential. It is stored encrypted in the vault and is NEVER echoed back, logged, or persisted to any table.
unit_idstringunit_id OPTIONALLY scopes the credential to a single org_unit (team). When set it MUST be a team the caller's tenant owns (IDOR-guarded). Mutually exclusive with agent_id. Absent + agent_id absent ⇒ org-level _default.
agent_idstringagent_id OPTIONALLY scopes the credential to a single agent. When set it MUST be an agent the caller's tenant owns (IDOR-guarded). Mutually exclusive with unit_id. Agent-scoped writes are allowed at L3 when the caller manages the agent's team, otherwise L4.

SetMCPServerCredentialResponse

SetMCPServerCredentialResponse confirms the write WITHOUT returning the secret.

FieldTypeLabelDescription
registry_idstringregistry_id echoes the server the credential was stored for.
credential_typestringcredential_type echoes the stored credential kind.
key_hintstringkey_hint is a masked fingerprint (last 4 chars only), safe to render in the UI to confirm which secret was stored — e.g. "••••AB12".
vault_refstringvault_ref is the resulting vault://provider_keys/&lt;org&gt;/&lt;scope&gt;/&lt;provider&gt; pointer the client patches into the server's upstream_auth_config bag (as token_vault_ref for bearer, or client_secret_vault_ref for oauth2), where <scope> is _default (org), the unit_id (team), or _agent_&lt;agent_id&gt; (agent). Only this opaque ref — never the raw secret — is persisted.
createdboolcreated is true when this was a first-time set, false when it rotated an existing secret for the same (tenant, scope, server, credential_type).
updated_atgoogle.protobuf.Timestampupdated_at is the server time the credential was written.

MCPServerCredentialService

MCPServerCredentialService is the thin tenant MCP-credential surface.

Write-only for secret MATERIAL: SetMCPServerCredential is the only path that accepts a raw secret, and no RPC ever returns the plaintext — a stored secret never leaves the vault. Delete removes (never reveals). ListMCPServerCredentials (core#1789) enumerates a team's stored credentials for the Credentials UI (client#566) but returns ONLY a MASKED hint per row (last 4 chars) — the mask is computed inside Postgres so the plaintext is never even materialized in the process. It is a VIEW-level read (L2+), NOT gated on the L4 write clearance, so a unit Manager can populate the UI.

Method NameRequest TypeResponse TypeDescription
SetMCPServerCredentialSetMCPServerCredentialRequestSetMCPServerCredentialResponseSetMCPServerCredential stores the raw upstream credential (a bearer token or an OAuth client_secret) for an MCP server in the tenant vault and returns only a masked hint + the resulting vault ref. The credential is stored at one of three scopes, selected by the OPTIONAL unit_id / agent_id fields (mutually exclusive; both absent ⇒ org-level _default legacy slot): - org: (org, "default", mcp<type><registry_id>) — L4 - team: (org, <unit_id>, mcp<type><registry_id>) — L4 - agent: (org, "agent"+agent_id, mcp<type>_<registry_id>) — L4, or L3 when the caller is the Manager of the agent's team. Idempotent per (org, scope, provider): a second call rotates the secret. The unit_id / agent_id MUST belong to the caller's tenant (IDOR-guarded via a real existence check) — a cross-tenant or unknown id is rejected PermissionDenied. Emits one mcp_server.credential.set audit event on success carrying only the credential_type + a masked hint + the scope — never the raw secret. Tenant is taken from the auth context.
DeleteMCPServerCredentialDeleteMCPServerCredentialRequestDeleteMCPServerCredentialResponseDeleteMCPServerCredential removes a stored upstream credential at the given scope (same org/team/agent selection + IDOR + clearance rules as Set). It NEVER returns secret material — only whether a row was removed + the vault ref that was targeted. Emits one mcp_server.credential.deleted audit event. Idempotent: deleting an absent credential succeeds with deleted=false.
ListMCPServerCredentialsListMCPServerCredentialsRequestListMCPServerCredentialsResponseListMCPServerCredentials enumerates every upstream MCP credential stored for a team (unit_id), one masked summary per (server, credential_type), to populate the team-page Credentials UI (client#566). SECURITY: it returns a MASKED hint only (e.g. "••••AB12", last 4 chars) — NEVER the plaintext. The mask is derived server-side inside Postgres (pgp_sym_decrypt is applied only to extract the last 4 characters) so the full secret is never materialized in the process, a log, or the response. Tenant is taken from the auth context; the requested unit_id MUST be a team the caller's tenant owns (IDOR-guarded, a cross-tenant / unknown id → NotFound). Clearance: a VIEW-level read (L2+), deliberately NOT the L4 write bar — a unit Manager can call it. Rows whose bound server was deregistered carry an empty server_name (the credential row still surfaces so the UI can offer cleanup). Read-only: emits no audit event and mutates nothing.

Top

upsquad/mcpserver/v1/mcpserver.proto

AddMCPGroupMemberRequest

AddMCPGroupMemberRequest attaches a server to a group.

FieldTypeLabelDescription
group_idstringgroup_id is the mcp_proxy_groups.id.
server_idstringserver_id is the mcp_servers.id to attach. Must be eligible and must not create a hard conflict with the existing member set.

AddMCPGroupMemberResponse

AddMCPGroupMemberResponse carries the post-attach group.

FieldTypeLabelDescription
groupMCPProxyGroupgroup is the group after the member was added.

AgentServerCell

AgentServerCell is one agent×server verdict in the D9 grid.

FieldTypeLabelDescription
server_idstringserver_id is the mcp_servers.id.
server_namestringserver_name is the server's display name.
verdictstringverdict is the effective outcome for this agent×server pair: allowed (every gate passed) or denied (a gate denied — see reason).
reasonDenialReasonreason is the machine-resolved denial cause; UNSPECIFIED when verdict is allowed. Populated most-global-first (the first denying gate wins).

AgentServerEntitlements

AgentServerEntitlements is the per-agent row of the D9 denial-reason grid.

FieldTypeLabelDescription
agent_idstringagent_id is the agents.id.
agent_namestringagent_name is the agent's display name.
clearanceint32clearance is the agent's clearance level (agents.clearance, 1..5) — the value compared against each server's min_clearance floor.
serversAgentServerCellrepeatedservers is one cell per MCP server relevant to the team, server-id sorted.

ApproveMCPServerBindingRequest

ApproveMCPServerBindingRequest approves a single pending binding.

FieldTypeLabelDescription
binding_idstringbinding_id is the mcp_server_units.id to approve.

ApproveMCPServerBindingResponse

ApproveMCPServerBindingResponse carries the post-approve binding.

FieldTypeLabelDescription
bindingMCPServerBindingbinding is the binding after the approve transition.

CreateMCPGroupRequest

CreateMCPGroupRequest creates a group under a team unit.

FieldTypeLabelDescription
unit_idstringunit_id is the team (org_unit) the group is scoped to.
namestringname is a human-readable label (2..64 chars), unique per org among active groups.
member_server_idsstringrepeatedmember_server_ids are the initial member mcp_servers.id values. May be empty (an empty group is created and members added later). Every id must be eligible (server + binding approved for unit, eligible transport) and the set must be conflict-free.

CreateMCPGroupResponse

CreateMCPGroupResponse carries the freshly created group.

FieldTypeLabelDescription
groupMCPProxyGroupgroup is the newly created group with its proxy URL.

DeleteMCPGroupRequest

DeleteMCPGroupRequest soft-deletes a group.

FieldTypeLabelDescription
group_idstringgroup_id is the mcp_proxy_groups.id to soft-delete.

DeleteMCPGroupResponse

DeleteMCPGroupResponse reports whether a row was updated.

FieldTypeLabelDescription
deletedbooldeleted is true when a row was actually soft-deleted. Idempotent — returns false when the group was already deleted or never existed.

DenyMCPServerBindingRequest

DenyMCPServerBindingRequest denies a single pending binding.

FieldTypeLabelDescription
binding_idstringbinding_id is the mcp_server_units.id to deny.
reasonstringreason is an optional free-text explanation recorded on the binding and in the audit row.

DenyMCPServerBindingResponse

DenyMCPServerBindingResponse carries the post-deny binding.

FieldTypeLabelDescription
bindingMCPServerBindingbinding is the binding after the deny transition.

DeregisterMCPServerRequest

DeregisterMCPServerRequest soft-deletes a server registration.

FieldTypeLabelDescription
server_idstringserver_id is the mcp_servers.id to soft-delete.

DeregisterMCPServerResponse

DeregisterMCPServerResponse reports whether a row was updated.

FieldTypeLabelDescription
deregisteredboolderegistered is true when a row was actually updated. Idempotent — returns false when the server was already deleted.

EntitlementCheck

EntitlementCheck is one gate in a tool's check chain.

FieldTypeLabelDescription
gatestringgate names the check: server_status
resultstringresult is pass (gate satisfied), fail (gate denies), or conditional (an escalate policy that gates the call at run time via HITL).
detailstringdetail is a short human-readable explanation of this gate's outcome.
policy_idstringpolicy_id is the mcp_tool_policies.id for a tool_policy / org_deny_floor gate; empty for the status / binding gates.
cel_summarystringcel_summary is the whitespace-collapsed, length-capped summary of the matched policy's CEL argument-rule expression; empty for non-policy gates or a policy with no expression.

GetMCPGroupRequest

GetMCPGroupRequest selects a single group by id.

FieldTypeLabelDescription
group_idstringgroup_id is the mcp_proxy_groups.id.

GetMCPGroupResponse

GetMCPGroupResponse returns a group plus its aggregated tool surface.

FieldTypeLabelDescription
groupMCPProxyGroupgroup is the requested group.
aggregated_toolsstringrepeatedaggregated_tools is the prefixed ({server}__{tool}) tool surface the proxy would expose for this group's currently-eligible members, sorted — the exact wire tool-list an MCP client sees on initialize. Empty when the group has no eligible members.

GetMCPServerHealthRequest

GetMCPServerHealthRequest selects a single server by id.

FieldTypeLabelDescription
server_idstringserver_id is the mcp_servers.id.

GetMCPServerHealthResponse

GetMCPServerHealthResponse returns the last observed health snapshot.

FieldTypeLabelDescription
server_idstringserver_id echoes the requested id.
health_statusstringhealth_status is the stable string bucket.
last_seengoogle.protobuf.Timestamplast_seen is the last healthy-probe timestamp; zero when never healthy.
last_errorstringlast_error is the message from the most recent failed probe, empty when the server is healthy.

GetTeamEntitlementMatrixRequest

GetTeamEntitlementMatrixRequest selects the team to compute the matrix for.

FieldTypeLabelDescription
unit_idstringunit_id is the team (org_unit where unit_type=team) whose effective (server × tool) entitlements to compute. Validated against the caller's tenant — a team in another org resolves NotFound.

GetTeamEntitlementMatrixResponse

GetTeamEntitlementMatrixResponse carries one ServerEntitlement per MCP server bound to the team.

FieldTypeLabelDescription
unit_idstringunit_id echoes the requested team.
serversServerEntitlementrepeatedservers is one entry per MCP server bound to the team (any binding state), oldest-registration first — the same ordering ListMCPServers returns.
agentsAgentServerEntitlementsrepeatedagents is the ADR-0024 D9 per-agent × per-server denial-reason grid: for every agent in the team and every MCP server relevant to the team, the agent's verdict (allowed

ListMCPGroupsRequest

ListMCPGroupsRequest filters groups by team unit.

FieldTypeLabelDescription
unit_idstringunit_id is the team (org_unit) to list groups under.

ListMCPGroupsResponse

ListMCPGroupsResponse returns the active groups for a team.

FieldTypeLabelDescription
groupsMCPProxyGrouprepeatedgroups is the list of active (non-deleted) groups for the unit, oldest first. Unpaginated — a team is expected to define few groups in v1.

ListMCPServersRequest

ListMCPServersRequest filters the registry by team.

FieldTypeLabelDescription
unit_idstringunit_id is the team (org_unit) to list servers under.

ListMCPServersResponse

ListMCPServersResponse returns the active server registrations for a team.

FieldTypeLabelDescription
serversMCPServerrepeatedservers is the list of active (non-deleted) registrations for the unit. Response is unpaginated — teams are expected to register fewer than ~50 MCP servers in V1.

ListPendingMCPServerBindingsRequest

ListPendingMCPServerBindingsRequest selects the pending bindings for a team.

FieldTypeLabelDescription
unit_idstringunit_id is the team (org_unit) whose pending approval inbox to list.

ListPendingMCPServerBindingsResponse

ListPendingMCPServerBindingsResponse returns the pending bindings for a team.

FieldTypeLabelDescription
bindingsMCPServerBindingrepeatedbindings is the list of pending (server, unit) bindings, oldest-first.

MCPProxyGroup

MCPProxyGroup is the wire form of an mcp_proxy_groups row plus its active member server ids and the derived proxy URL. It is the AdapterMcpGroup shape the F4 client authoring UI (client#512/#519) binds to.

FieldTypeLabelDescription
idstringid is the stable UUID of the group. It is the {id} segment of the proxy URL {public_base}/mcp/group/{id}.
org_idstringorg_id is the owning tenant organisation UUID.
unit_idstringunit_id is the team (org_unit where unit_type=team) the group is scoped to.
namestringname is the group display name — unique per org among active groups.
member_server_idsstringrepeatedmember_server_ids are the mcp_servers.id values currently attached to the group (active memberships only), sorted for a stable wire order. A member id present here is not necessarily eligible right now — eligibility (server + binding approved, eligible transport) is applied by the proxy resolver at request time and reflected in GetMCPGroup's aggregated_tools.
proxy_urlstringproxy_url is the stable client-facing endpoint {public_base}/mcp/group/{id} an MCP client connects to.
created_bystringcreated_by is the member id that created the group.
created_atgoogle.protobuf.Timestampcreated_at is the row creation timestamp.
updated_atgoogle.protobuf.Timestampupdated_at is the last mutation timestamp (membership change or rename).

MCPServer

MCPServer is the wire form of an mcp_servers row.

FieldTypeLabelDescription
idstringid is the stable UUID of the server entry.
org_idstringorg_id is the owning tenant organisation UUID.
unit_idstringunit_id is the team (org_unit where unit_type=team) the server is registered under.
namestringname is the display name set by the team admin.
urlstringurl is the base URL the MCP client should connect to.
oauth_config_jsonstringoauth_config_json is the opaque OAuth configuration bag. Empty when no OAuth is required. Expected to hold only vault references, NOT raw secrets. When returning this field the service REDACTS any embedded raw_* / client_secret / token / password keys as a defence-in-depth measure.
health_statusstringhealth_status is the latest coarse bucket as a stable string (healthy
last_seengoogle.protobuf.Timestamplast_seen is the timestamp of the most recent successful probe. Zero when the server has never reported healthy.
created_atgoogle.protobuf.Timestampcreated_at is the row creation timestamp.
updated_atgoogle.protobuf.Timestampupdated_at is the last mutation timestamp.
approval_statusstringapproval_status is the per-team binding approval gate (ADR-0021 T2): pending
binding_idstringbinding_id is the mcp_server_units.id of the (server, unit) binding this row was read through. Empty on a bare server read. Used as the target of the Approve/Deny binding RPCs.
statusstringstatus is the lifecycle bucket as a stable string (pending
tool_schemastringtool_schema is the registration-probe-captured tool surface: a JSON array of {name, description, input_schema} objects serialized as a string. Empty array ([]) until the first successful probe.
transportstringtransport is the observed MCP wire transport captured at probe time (stdio
versionint32version is the monotonic per-server schema version, bumped when the captured tool_schema changes. Starts at 1.
min_clearanceint32min_clearance is the registry-level clearance floor (ADR-0024 D6, #1991): an agent resolves/calls this server only when its own clearance (agents.clearance, 1..5) is >= this value. 0 (the default) means NO floor. Enforced defence-in-depth at the session-snapshot freeze and the gateway edge. Set/shown by the registry UI (L4 edit floor).

MCPServerBinding

MCPServerBinding is the wire form of a mcp_server_units row (the MCP↔team binding) joined to its server's display name.

FieldTypeLabelDescription
idstringid is the mcp_server_units.id — the target of Approve/Deny.
org_idstringorg_id is the owning tenant organisation UUID.
server_idstringserver_id is the bound mcp_servers.id.
server_namestringserver_name is the bound server's display name (join convenience).
unit_idstringunit_id is the team (org_unit) the server is bound to.
approval_statusstringapproval_status is pending
requested_bystringrequested_by is the member who registered the binding (the approval request actor). Empty when unknown.
decided_bystringdecided_by is the Manager member who approved/denied. Empty while pending.
decided_atgoogle.protobuf.Timestampdecided_at is the decision timestamp. Zero while pending.
decision_reasonstringdecision_reason is the optional free-text reason (esp. for denial).
created_atgoogle.protobuf.Timestampcreated_at is the binding creation timestamp.
visibilitystringvisibility is the binding's org-tree reach (ADR-0022 W2 #1739): inherit_down
credential_modestringcredential_mode is the binding's upstream-credential model (ADR-0022 W2 #1739): team_shared
require_per_agentboolrequire_per_agent asserts the binding MUST be per-agent-credentialled (ADR-0022 W2 #1739). See RegisterMCPServerRequest.
private_upstream_approvedboolprivate_upstream_approved is the ADR-0025 (#2019) L5-gated capability that GATES whether Manager approval auto-seeds a vetted private-upstream egress row (allow_private=true, pinned_cidr) so a legitimate in-cluster upstream is reachable through the egress guard. Default false — the SSRF floor (metadata/loopback/link-local) stays denied regardless.
private_pinned_cidrstringprivate_pinned_cidr is the CIDR the resolved (and connect-time re-validated) upstream IP must fall inside when private_upstream_approved is set — e.g. a GKE Service CIDR or the beta-dev docker bridge 172.18.0.0/16. Empty when the capability is off.

RegisterMCPServerRequest

RegisterMCPServerRequest registers a new MCP server under an org_unit.

FieldTypeLabelDescription
unit_idstringunit_id is the org_unit (pillar OR team — ADR-0022 W2) under which the server is registered. MUST reference a unit in the caller's tenant.
namestringname is a human-readable label (2..64 chars).
urlstringurl is the MCP server base URL (must be http:// or https://).
oauth_config_jsonstringoauth_config_json is optional; see MCPServer.oauth_config_json for format and secret-handling rules.
visibilitystringvisibility governs how far the binding reaches down/across the org tree (ADR-0022 W2 #1739): inherit_down
credential_modestringcredential_mode governs the upstream-credential model for the binding (ADR-0022 W2 #1739): team_shared
require_per_agentboolrequire_per_agent is a policy assertion that the binding MUST be per-agent-credentialled — the resolver/gateway rejects a team-shared credential for this binding when true. Defaults false. Independent of credential_mode so the intent can be flagged before per-agent credentials are provisioned.
min_clearanceint32min_clearance is the registry-level clearance floor (ADR-0024 D6, #1991): 0..5, where 0 (the default when unset) means NO floor. An agent may resolve or call this server only when its own clearance (agents.clearance) is >= this value. A value outside 0..5 is rejected invalid_argument.

RegisterMCPServerResponse

RegisterMCPServerResponse carries the freshly inserted server row.

FieldTypeLabelDescription
serverMCPServerserver is the newly created registry row.

RemoveMCPGroupMemberRequest

RemoveMCPGroupMemberRequest detaches a server from a group.

FieldTypeLabelDescription
group_idstringgroup_id is the mcp_proxy_groups.id.
server_idstringserver_id is the mcp_servers.id to detach.

RemoveMCPGroupMemberResponse

RemoveMCPGroupMemberResponse carries the post-detach group.

FieldTypeLabelDescription
groupMCPProxyGroupgroup is the group after the member was removed.

ServerEntitlement

ServerEntitlement is the per-server slice of the matrix: the server's lifecycle + binding gates, its derived identity-rung, and the per-tool verdicts.

FieldTypeLabelDescription
server_idstringserver_id is the mcp_servers.id.
server_namestringserver_name is the server's display name.
server_statusstringserver_status is the lifecycle bucket (pending
approval_statusstringapproval_status is the per-team binding gate (pending
identity_rungstringidentity_rung is the upstream identity mode derived SOLELY from the oauth_config_json type key — one of gateway_identity (oauth2), shared_token (bearer), or anonymous (none / unset). No secret or vault-reference material is ever read or returned.
toolsToolEntitlementrepeatedtools is one verdict entry per tool on the server's captured schema. Empty when the server has never been probed (tool_schema is []).

SetMCPServerStatusRequest

SetMCPServerStatusRequest moves a server between approved and disabled.

FieldTypeLabelDescription
server_idstringserver_id is the mcp_servers.id to transition.
statusstringstatus is the target lifecycle state — MUST be 'approved' or 'disabled'. Any other value (including 'pending') is rejected invalid_argument.
reasonstringreason is an optional free-text explanation recorded in the audit row.

SetMCPServerStatusResponse

SetMCPServerStatusResponse carries the post-transition server row.

FieldTypeLabelDescription
serverMCPServerserver is the server after the status transition (or the unchanged current row on an idempotent no-op).

SetMCPServerWithholdRequest

SetMCPServerWithholdRequest sets/clears a Manager subtree-withhold on a server for a unit.

FieldTypeLabelDescription
unit_idstringunit_id is the org_units.id at which the withhold applies. The caller MUST be this unit's Manager (org_units.manager_member_id). The withhold scopes to this unit and its whole subtree.
server_idstringserver_id is the mcp_servers.id to withhold / un-withhold for the subtree.
withheldboolwithheld=true sets the withhold (subtracts the server from the subtree); withheld=false clears it (the subtree may again inherit / receive the server through ordinary grants). Idempotent in both directions.
reasonstringreason is an optional free-text explanation recorded in the audit row.

SetMCPServerWithholdResponse

SetMCPServerWithholdResponse reports the resulting withhold state.

FieldTypeLabelDescription
unit_idstringunit_id echoes the unit the withhold applies at.
server_idstringserver_id echoes the withheld / un-withheld server.
withheldboolwithheld is the resulting state (true = an active withhold now exists).

ToolEntitlement

ToolEntitlement is the verdict for a single (server, tool) pair plus the ordered chain of checks that produced it.

FieldTypeLabelDescription
tool_namestringtool_name is the tool's name from the server's captured tool_schema.
verdictstringverdict is the effective outcome: allowed (no gating policy), conditional (an escalate/HITL policy may gate the call at run time), or denied (a gate failed — disabled server, unapproved binding, or a matching deny policy / org deny floor).
check_chainEntitlementCheckrepeatedcheck_chain is the ordered list of gates evaluated for this tool, each recording its result and (for policy gates) the matched policy id and a summarised CEL expression. Read top-to-bottom it explains the verdict.

UpdateMCPServerBindingRequest

UpdateMCPServerBindingRequest edits an existing binding's write-surface knobs. Each field is presence-gated by a paired *_set flag so a caller can change one knob without disturbing the others (proto3 cannot otherwise tell an unset scalar from its zero value). At least one *_set flag MUST be true.

FieldTypeLabelDescription
binding_idstringbinding_id is the mcp_server_units.id to edit.
visibilitystringvisibility is the new reach (inherit_down
visibility_setboolvisibility_set gates whether visibility is applied.
credential_modestringcredential_mode is the new credential model (team_shared
credential_mode_setboolcredential_mode_set gates whether credential_mode is applied.
require_per_agentboolrequire_per_agent is the new policy assertion, applied only when require_per_agent_set is true.
require_per_agent_setboolrequire_per_agent_set gates whether require_per_agent is applied.
private_upstream_approvedboolprivate_upstream_approved is the ADR-0025 (#2019) vetted private-upstream capability, applied only when private_upstream_approved_set is true. Writing it (true or false) requires L5 clearance — the RPC rejects a lower-clearance caller PermissionDenied. Setting it true REQUIRES private_pinned_cidr to be a valid CIDR (this call or already on the binding) that does NOT overlap the SSRF floor.
private_upstream_approved_setboolprivate_upstream_approved_set gates whether private_upstream_approved is applied.
private_pinned_cidrstringprivate_pinned_cidr is the CIDR the approved private upstream must resolve inside (e.g. a GKE Service CIDR or 172.18.0.0/16), applied only when private_pinned_cidr_set is true. Also L5-gated.
private_pinned_cidr_setboolprivate_pinned_cidr_set gates whether private_pinned_cidr is applied.

UpdateMCPServerBindingResponse

UpdateMCPServerBindingResponse carries the post-edit binding.

FieldTypeLabelDescription
bindingMCPServerBindingbinding is the binding after the edit.

UpdateMCPServerRequest

UpdateMCPServerRequest edits a registered server's name / url / oauth_config_type. Each field is presence-gated by a paired *_set flag so a caller can change one knob without disturbing the others (proto3 cannot otherwise tell an unset scalar from its zero value). At least one *_set flag MUST be true.

FieldTypeLabelDescription
server_idstringserver_id is the mcp_servers.id to edit. MUST reference a server in the caller's tenant (a server in another org resolves NotFound).
namestringname is the new human-readable label (2..64 chars), applied only when name_set is true. Rejected already_exists if it collides with another active server name in the org.
name_setboolname_set gates whether name is applied.
urlstringurl is the new MCP server base URL (must be http:// or https://), applied only when url_set is true. Changing the url triggers a re-probe that refreshes tool_schema + health_status; the egress allow-list still applies (a new host may need founder allow-listing before the probe can reach it, exactly as at registration).
url_setboolurl_set gates whether url is applied.
oauth_config_typestringoauth_config_type is the new upstream auth mode — one of none
oauth_config_type_setbooloauth_config_type_set gates whether oauth_config_type is applied.
min_clearanceint32min_clearance is the new registry clearance floor (ADR-0024 D6, #1991), applied only when min_clearance_set is true. 0..5, where 0 means NO floor. A value outside 0..5 is rejected invalid_argument.
min_clearance_setboolmin_clearance_set gates whether min_clearance is applied.

UpdateMCPServerResponse

UpdateMCPServerResponse carries the post-edit server row (oauth_config_json redacted on the way out, as everywhere).

FieldTypeLabelDescription
serverMCPServerserver is the server after the edit.

DenialReason

DenialReason is the machine-resolved cause a single agent×server cell is denied (ADR-0024 D9). UNSPECIFIED means allowed (no denial). Reasons are evaluated MOST-GLOBAL-FIRST; the first that matches wins, so a server that is both disabled and below the agent's clearance reports ORG_DISABLED.

NameNumberDescription
DENIAL_REASON_UNSPECIFIED0UNSPECIFIED is the proto3 sentinel; it denotes an ALLOWED cell (no gate denied). A denied cell always carries a specific reason below.
DENIAL_REASON_ORG_DISABLED1ORG_DISABLED — mcp_servers.status='disabled' (registry L5 kill-switch, D4a).
DENIAL_REASON_NOT_BOUND2NOT_BOUND — no approved grant binding resolvable to the team (D1): the server is not in the team's grant union (never bound, binding not approved, or a non-inheriting ancestor/sibling binding).
DENIAL_REASON_MANAGER_SUBTREE_WITHHELD3MANAGER_SUBTREE_WITHHELD — a binding_kind='withhold' on an ancestor-or-self unit removes an otherwise-granted server for the team's subtree (D4b).
DENIAL_REASON_CLEARANCE_FLOOR4CLEARANCE_FLOOR — the agent's clearance is below the server's registry min_clearance floor (D6).
DENIAL_REASON_CREATION_ALLOWLIST5CREATION_ALLOWLIST — the server is narrowed out by the agent's per-agent creation-time MCP server allowlist (agent_configurations.tools, #1744/D7).

HealthStatus

HealthStatus enumerates the coarse bucket of the last probe outcome. The string-typed health_status field on MCPServer carries the same value so the message stays forward-compatible with richer status vocabularies added server-side.

NameNumberDescription
HEALTH_STATUS_UNSPECIFIED0UNSPECIFIED is the default sentinel required by proto3.
HEALTH_STATUS_UNKNOWN1UNKNOWN means no probe has completed yet.
HEALTH_STATUS_HEALTHY2HEALTHY means the last probe returned a successful result.
HEALTH_STATUS_DEGRADED3DEGRADED means the server is reachable but reports partial failure.
HEALTH_STATUS_UNREACHABLE4UNREACHABLE means the last probe failed to connect or timed out.

MCPServerService

MCPServerService manages the team-scoped MCP server registry.

Method NameRequest TypeResponse TypeDescription
RegisterMCPServerRegisterMCPServerRequestRegisterMCPServerResponseRegisterMCPServer creates a new MCP server entry under an org_unit (pillar OR team — ADR-0022 W2 #1739). If oauth_config_json is non-empty it is opaque to the platform — the caller is responsible for ensuring any embedded secret has already been stored in the vault; only a stable reference like "vault://provider_keys/<org>/<unit>/<provider>" should appear in this JSON blob. The service itself NEVER persists raw tokens.

The attachment's visibility + credential_mode are set on the request (see RegisterMCPServerRequest). unit_id MUST reference a unit in the caller's tenant — a cross-tenant or unknown unit is rejected invalid_argument (IDOR guard).

Requires mcp_servers.manage with ScopeOrgUnit of unit_id. | | ListMCPServers | ListMCPServersRequest | ListMCPServersResponse | ListMCPServers returns all active MCP server entries for a unit.

Requires mcp_servers.view. | | DeregisterMCPServer | DeregisterMCPServerRequest | DeregisterMCPServerResponse | DeregisterMCPServer soft-deletes an MCP server entry.

Requires mcp_servers.manage. | | GetMCPServerHealth | GetMCPServerHealthRequest | GetMCPServerHealthResponse | GetMCPServerHealth returns the last observed health snapshot for a server. Health itself is produced by the MCP middleware / probe loop; this RPC is a read-only view of the stored status.

Requires mcp_servers.view. | | ListPendingMCPServerBindings | ListPendingMCPServerBindingsRequest | ListPendingMCPServerBindingsResponse | ListPendingMCPServerBindings returns the pending MCP↔team bindings for a unit — the unit Manager's approval inbox (ADR-0021 T2 / decision 8). A binding is created 'pending' by RegisterMCPServer and is INERT (does not resolve into the team's effective config) until approved.

Requires mcp_servers.view. | | ApproveMCPServerBinding | ApproveMCPServerBindingRequest | ApproveMCPServerBindingResponse | ApproveMCPServerBinding transitions a pending binding to approved. ONLY the unit's Manager (org_units.manager_member_id, Org v2.4 authority) may call this; a non-Manager caller is rejected permission_denied. The transition is terminal — a binding that is already approved/denied returns failed_precondition. Writes an mcp_binding_approved audit row.

Requires mcp_servers.manage + Manager identity (service-layer check). | | DenyMCPServerBinding | DenyMCPServerBindingRequest | DenyMCPServerBindingResponse | DenyMCPServerBinding transitions a pending binding to denied (with an optional reason). Same Manager-only authority + terminal semantics as ApproveMCPServerBinding. Writes an mcp_binding_denied audit row.

Requires mcp_servers.manage + Manager identity (service-layer check). | | UpdateMCPServerBinding | UpdateMCPServerBindingRequest | UpdateMCPServerBindingResponse | UpdateMCPServerBinding edits an EXISTING binding's write-surface knobs (ADR-0022 W2 #1739): visibility, credential_mode, require_per_agent. Only the binding unit's Manager (org_units.manager_member_id — the SAME authority as Approve/Deny, no new governance actor) may call it; a non-Manager caller is permission_denied and a unit with no Manager is failed_precondition (fail closed). Every field is optional-by-presence: a *_set companion flag gates whether the paired value is applied, so a caller can change visibility alone without disturbing credential_mode (proto3 cannot distinguish an unset string/bool from its zero value otherwise). The edit is tenant-scoped (RLS) and writes an mcp_binding_updated audit row capturing the before/after of each changed field. The binding's approval_status is untouched — this RPC does not approve/deny.

Requires mcp_servers.manage + Manager identity (service-layer check). | | SetMCPServerStatus | SetMCPServerStatusRequest | SetMCPServerStatusResponse | SetMCPServerStatus moves a registered server between the 'approved' and 'disabled' lifecycle states (ADR-0021 T1 — the global kill-switch, core#1715). A registered server lands 'approved' (registry-live) but serves ZERO teams until each team's per-unit binding is Manager-approved (the T2 gate is unchanged). 'disabled' drops the server from ALL resolution paths (proxy_upstreams projection + group//mcp/{id} resolvers) regardless of any approved binding — an independent, orthogonal gate — and 'approved' restores it. status ∈ {approved, disabled}; any other value is invalid_argument. Only the owning unit's Manager (org_units.manager_member_id — the SAME authority as ApproveMCPServerBinding, no new governance actor) may call it; a non-Manager caller is permission_denied and a unit with no Manager is failed_precondition (fail closed). Idempotent: setting the current status is a no-op that returns the current row. Writes an mcp_server_{approved,disabled} audit row on an actual transition.

Requires mcp_servers.manage + Manager identity (service-layer check). | | SetMCPServerWithhold | SetMCPServerWithholdRequest | SetMCPServerWithholdResponse | SetMCPServerWithhold sets or clears a Manager subtree-WITHHOLD on an MCP server for a unit (ADR-0024 D4b, #1992). A withhold is an mcp_server_units row with binding_kind='withhold' keyed to (unit, server); it SUBTRACTS that server from the effective MCP set of the unit AND every unit in the unit's subtree — the resolver's mcpHomeForUnits subtract-after-union pass removes any server withheld on a unit that is ancestor-or-self of the resolving team, so the reach is exactly the subtree (a sibling subtree / the org root are untouched). The withhold WINS over any inherited or subtree-direct grant. This is the Manager-scoped complement to the L5 org-wide kill-switch (SetMCPServerStatus, D4a) — a Manager may withhold within their own subtree, the root Manager reaches org-wide. withheld=true sets it (idempotent); withheld=false clears it. Only the unit's Manager (org_units.manager_member_id) may call it; a non-Manager is permission_denied and a unit with no Manager is failed_precondition (fail closed). Writes an mcp_subtree_withheld audit row on both set and clear.

Requires mcp_servers.manage + Manager identity (service-layer check). | | UpdateMCPServer | UpdateMCPServerRequest | UpdateMCPServerResponse | UpdateMCPServer edits a REGISTERED server's name / url / oauth_config_type (#1775) — the edit path that previously required a deregister + re-register to fix a typo'd URL, name, or auth mode. Every field is presence-gated by a paired *_set flag so a caller can change one without disturbing the others (proto3 cannot distinguish an unset scalar from its zero value otherwise); at least one *_set MUST be true. Tenant-scoped: the server must belong to the caller's org (a server in another org resolves NotFound). Requires L4 clearance (the same tenant-edit floor as setting an upstream credential).

Changing the url RE-PROBES the upstream through the SAME egress-guarded probe path registration uses, refreshing tool_schema + health_status. The egress allow-list still applies — a new host may need founder allow-listing before the probe can reach it (health lands 'unreachable' until then), exactly as at registration. Changing oauth_config_type writes ONLY the bag's type key — NEVER a raw secret; switching to a mode that needs a fresh secret leaves the vault-ref empty for SetMCPServerCredential (+ the #1774 backfill) to re-wire, while an unchanged type preserves the existing ref. Bindings are untouched. Writes an mcp_server_updated audit row capturing the before/after of each changed field (no secrets).

Requires mcp_servers.manage + L4 clearance (service-layer check). | | CreateMCPGroup | CreateMCPGroupRequest | CreateMCPGroupResponse | CreateMCPGroup creates a group aggregating N MCP servers behind ONE /mcp/group/{id} endpoint, scoped to a team unit. Every member_server_id must be server-approved (T1) AND binding-approved (T2) for the unit and on an eligible transport (streamable_http); an ineligible member is rejected invalid_argument / failed_precondition. The requested member set is run through the SAME mcpproxy.ValidateMembers gate the proxy edge applies, so a group the RPC accepts is one the proxy will serve (no hard tool-name conflicts, no duplicate server names). Only the unit's Manager (org_units.manager_member_id) may create a group. Writes an mcp_group_created audit row.

Requires mcp_servers.manage + Manager identity (service-layer check). | | ListMCPGroups | ListMCPGroupsRequest | ListMCPGroupsResponse | ListMCPGroups returns the active groups for a team unit (RLS-scoped to the caller's org, migration 131). Each group carries its member server ids + the stable proxy URL.

Requires mcp_servers.view. | | GetMCPGroup | GetMCPGroupRequest | GetMCPGroupResponse | GetMCPGroup returns a single group with its member ids, the stable /mcp/group/{id} proxy URL, and the AGGREGATED (prefixed {server}__{tool}) tool surface the proxy would expose — computed from the currently-eligible members via the SAME mcpproxy.Aggregate the edge uses.

Requires mcp_servers.view. | | DeleteMCPGroup | DeleteMCPGroupRequest | DeleteMCPGroupResponse | DeleteMCPGroup soft-deletes a group (idempotent). Only the unit's Manager may delete it. Writes an mcp_group_deleted audit row.

Requires mcp_servers.manage + Manager identity (service-layer check). | | AddMCPGroupMember | AddMCPGroupMemberRequest | AddMCPGroupMemberResponse | AddMCPGroupMember attaches an MCP server to an existing group. The server must be eligible (as CreateMCPGroup) and the resulting member set must pass ValidateMembers. Only the unit's Manager may change membership. Writes an mcp_group_member_added audit row.

Requires mcp_servers.manage + Manager identity (service-layer check). | | RemoveMCPGroupMember | RemoveMCPGroupMemberRequest | RemoveMCPGroupMemberResponse | RemoveMCPGroupMember detaches an MCP server from a group (idempotent). Only the unit's Manager may change membership. Writes an mcp_group_member_removed audit row.

Requires mcp_servers.manage + Manager identity (service-layer check). | | GetTeamEntitlementMatrix | GetTeamEntitlementMatrixRequest | GetTeamEntitlementMatrixResponse | GetTeamEntitlementMatrix computes, live and read-only, the (team × server × tool) entitlement matrix for a team unit: for every MCP server bound to the team and every tool on that server's captured schema, a verdict (allowed | conditional | denied) plus the CHECK CHAIN that explains it — the server lifecycle-status gate (ADR-0021 T1 kill-switch), the per-team binding-approval gate (T2), the matching tool policies with their CEL expression summarised, and the org-wide deny floor. Each server also carries its identity-rung derived from the upstream auth mode (oauth2 → gateway_identity, bearer → shared_token, none → anonymous).

Sources: mcp_servers (status, tool_schema, oauth_config_json TYPE ONLY — NEVER any secret / vault-ref material), mcp_server_units (binding approval), mcp_tool_policies. Tool-policy precedence is NOT reimplemented here — it is computed by the SAME internal/guardrails resolve query used at the tool-call gate (deny outranks escalate across the whole team home-chain cascade), so the matrix and the live gate can never disagree.

Read-only (no writes). Requires L2+ clearance; the team is validated against the caller's tenant (a team in another org resolves NotFound). The response also carries the ADR-0024 D9 per-agent × per-server denial-reason grid (agents): each cell is an agent's verdict for a server plus the machine-resolved reason when denied, evaluated most-global-first, reusing the SAME resolver / clearance / allowlist predicates the runtime enforces (#1993).

Requires mcp_servers.view. |

Scalar Value Types

.proto TypeNotesC++JavaPythonGoC#PHPRuby
doubledoubledoublefloatfloat64doublefloatFloat
floatfloatfloatfloatfloat32floatfloatFloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32intintegerBignum or Fixnum (as required)
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/longint64longinteger/stringBignum
uint32Uses variable-length encoding.uint32intint/longuint32uintintegerBignum or Fixnum (as required)
uint64Uses variable-length encoding.uint64longint/longuint64ulonginteger/stringBignum or Fixnum (as required)
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32intintegerBignum or Fixnum (as required)
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/longint64longinteger/stringBignum
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.uint32intintuint32uintintegerBignum or Fixnum (as required)
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.uint64longint/longuint64ulonginteger/stringBignum
sfixed32Always four bytes.int32intintint32intintegerBignum or Fixnum (as required)
sfixed64Always eight bytes.int64longint/longint64longinteger/stringBignum
boolboolbooleanbooleanboolboolbooleanTrueClass/FalseClass
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicodestringstringstringString (UTF-8)
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteByteStringstringString (ASCII-8BIT)