Part 30 of 40 · 5 min read
A capability registry for tools the agent may actually use
Experimental · Work in progress · Internal R&D
MCP discovery, typed contracts, role intersection, connection aliases and controlled composition.
Arunank Sharan · Kuzushi Labs ·
In this article
The interesting question is not how many tools an agent can discover. It is which tools should be available for this task, under this role, against this customer's records, with this budget and approval state.
A solo-company platform needs a capability registry because the same integration can support very different actions. Reading a CRM contact, changing a commercial stage and sending a customer email should not inherit the same authority merely because they share a provider account. The registry makes those distinctions visible before the model proposes work.
Describe effects, not just function signatures
A useful tool contract includes name, input schema, output schema, effect type, permitted roles, connection scope, evidence requirements, idempotency behaviour, expected cost class and recovery procedure. A tool named update_record is too broad if it can alter both an internal note and a payment beneficiary.
name: quote.prepare_send
version: 1
mode: propose_write
roles: [sales]
connection_alias: sales_mailbox
subject_type: opportunity
requires:
- current_quote_revision
- verified_recipient
- communication_permission
approval: exact_content_and_recipient
execution_action: quote.dispatch_reviewed
recovery: reconcile_provider_receipt
This is a proposed registry entry. The agent-facing capability prepares an action; the execution service checks the current review and dispatches it. Separating those interfaces keeps the permission boundary inspectable even if the model route changes.
Compose from an intersection
The available set should be the intersection of the role's capabilities, the task's needs, enabled tenant connections, environment restrictions and current policy. Deny by default when any required scope is missing.
The public harness demonstrates the role-and-enabled subset:
from company_lab.harness import Tool, compose
catalogue = [
Tool("contact.read", frozenset({"sales", "support"}), "read"),
Tool("quote.propose", frozenset({"sales"}), "write"),
Tool("payment.execute", frozenset({"finance"}), "write"),
]
tools = compose(catalogue, role="sales",
enabled={"contact.read", "quote.propose", "payment.execute"})
assert set(tools) == {"contact.read", "quote.propose"}
The fixture does not implement tenant authentication or a production policy engine. Those checks belong around this composition step and again at action execution. Tool visibility helps the model behave sensibly; it is not the final security boundary.
Where MCP helps
MCP provides a standard way for a client to discover and invoke tools with structured contracts. That makes it useful for connecting a harness to multiple tool servers. Its tool interface does not define this company's approval policy, invoice state machine or spending limits. Those remain application responsibilities. This design references the versioned specification rather than assuming every server implements identical behaviour. MCP tools specification, 2025-11-25.
Treat newly discovered tool descriptions as integration metadata to review. Do not automatically make every remote capability available to every agent. Pin or record the accepted schema version, validate changes and test the adapter before expanding authority.
Credentials stay on the server side
The model should reference a connection alias, not a token. The tool gateway resolves that alias within the authenticated tenant and checks the requested resource. Logging should retain the alias and provider account identity without exposing secrets.
MCP's HTTP authorisation specification addresses access to protected servers. It does not remove the need to authorise the particular business action or prevent a confused integration from operating on the wrong account. Keep server access, resource scope and business approval as separate checks. MCP authorisation.
A revoked connection must become unavailable to new dispatches even if an earlier agent episode saw the tool. A queued action can outlive the permission that originally allowed its proposal.
Validate tool outputs as well as inputs
An input schema can reject a missing currency or malformed invoice ID. The output contract should distinguish success, a permanent refusal, retryable failure and uncertain external state. A free-form string saying “probably sent” is not a receipt.
{
"operation_id": "send-017",
"status": "UNKNOWN",
"provider_receipt": null,
"recovery": "LOOKUP_BEFORE_RETRY",
"retry_after_seconds": 30
}
Only the adapter should interpret provider-specific response details. The domain layer consumes the normalised contract. Preserve the raw response securely when needed for diagnosis, with access and retention controls; do not put account tokens or complete customer messages into general logs.
Handle tool-schema evolution deliberately
A renamed field can break an agent prompt. A new optional field can change default behaviour. A provider may deprecate an endpoint or widen the meaning of an action. Record tool versions in episode traces and evaluate changes against representative fixtures.
For a breaking change, keep the old adapter available for in-flight jobs until they complete or are explicitly migrated. Replaying a job against a new schema without recording that change makes recovery hard to explain.
Capability composition can be dynamic without being arbitrary. A delivery task may gain read-only access to a particular repository after the work order links it. It should not gain access to every repository because the task contains the word “code.”
Test the denied paths
The practical exercise is a sales agent attempting a payment tool, a revoked mailbox during a queued send, a remote schema change and an output containing an instruction to reveal a secret. The first two should be denied by authority checks, the schema change should trigger adapter review, and the output instruction should remain untrusted data.
The registry is useful when those outcomes are predictable. Its value is making a composed agent small enough to understand and constrained enough to operate, while still allowing the founder to add a new connector through a documented contract.