Skip to main content

3tears Registry

MCP-compatible tool registry for the 3tears tool system. Routes tool calls between agents and tool pods via NATS request/reply.

Part of the 3tears framework.

Components

  • ToolCatalog -- in-memory index of registered tool pods, backed by a NATS KV bucket for recovery across restarts.
  • RegistrationHandler -- subscribes to {ns}.tools.register and mutates the catalog.
  • HeartbeatMonitor -- sweeps pods whose heartbeats fell behind the timeout and evicts their endpoints.
  • DiscoveryHandler -- serves {ns}.tools.discover for pod-readiness polling.
  • CallProxy -- the hot path. Subscribes to {ns}.tools.call, authorizes via AgentToolAuthorizer, selects an endpoint via the configured RoutingStrategy, and forwards the call to the tool pod via NATS request/reply with identity + correlation carried through the CallContext envelope.
  • RegistryRbacStack -- self-contained rbac surface the standalone server constructs against the connected NATS client: NATS-proxy NamespaceCollection + four rbac metadata Collections + AclCache + invalidation subscribers. The _run_server() entry point uses this to wire RbacEvaluatorAuthorizer without any host-application loaders, so a standalone server no longer defaults to deny-all.

Authorization

Tool dispatch authorization lives behind the AgentToolAuthorizer protocol. Implementations receive the calling agent id, the invoking user id (from CallContext.user_id), and the fully qualified tool name, and return a boolean decision.

Production deployments wire RbacEvaluatorAuthorizer (in threetears.registry.rbac_authorizer) which delegates to the unified rbac evaluator from threetears.agent.acl:

  • The platform-side ToolNamespaceEmitter listens on {ns}.tools.register and upserts a platform.namespaces row of type tool per tool in every RegistrationManifest. The canonical name shape is tools.<sanitized-mcp-name>.<sanitized-version> (per build_namespace_name); metadata carries the pre-sanitized natural-identity fields mcp_name / mcp_version / pod_id so downstream pattern matching (the access materializer's agent.yaml access.tools patterns) does not need to reverse the sanitization rules.
  • The authorizer resolves the tool namespace via an injected NamespaceCollection. The signature is is_authorized(agent_id, user_id, tool_name, tool_version). The implementation builds the canonical lookup key via build_namespace_name(PLURAL_PREFIX_TOOL, tool_name, tool_version) rather than passing the raw mcp_name directly, so the lookup matches the row the emitter wrote.
  • evaluate_decision resolves the two-sided grant chain: user side (groups the invoking user is in) intersected with agent side (groups the calling agent is in, short-circuited by namespace ownership). The decision is cached in threetears.agent.acl.AclCache with TTL + fine-grained invalidation; cross-process rbac mutations purge the cache promptly via the acl.{membership,assignment,role}.invalidate subjects the RegistryRbacStack subscribes to on startup.

Defense in depth: when user_id=None (tool dispatch without user identity) the authorizer denies unconditionally. When the namespace Collection's get_by_name returns None (tool registered but namespace row not yet visible) it denies. This catches registration races rather than defaulting to allow.

Platform-built-in tools land with owner_agent_id=NULL, customer_id=NULL. There is no implicit "anyone can call" behaviour for them. Grants are managed via explicit assignments on the platform-seeded ToolCaller role (same pattern as shared-type workspaces).

RbacEvaluatorAuthorizer is the only authorizer the production server wires: no dual-enforcement window, no back-compat aliases. The declarative access.tools expression on agent.yaml stays as operator-facing syntax and is translated to RBAC assignments at bootstrap.

Dev-mode authorizers

AllowAllAuthorizer permits every dispatch unconditionally, enabled by THREETEARS_REGISTRY_ALLOW_ALL_TOOLS=true. Use only in local dev containers when an explicit RBAC bypass is needed.

DenyAllAuthorizer refuses every dispatch. Available as a panic-button kill switch via THREETEARS_REGISTRY_FORCE_DENY_ALL=true. It is also the millisecond-window placeholder the server holds before the rbac stack is wired against the live NATS client during serve().

Standalone entry point

python -m threetears.registry

Reads THREETEARS_NATS_URL (defaults to nats://localhost:4222) and THREETEARS_NATS_SUBJECT_NAMESPACE (the NATS subject namespace).

By default the entry point wires RbacEvaluatorAuthorizer against a self-contained RegistryRbacStack (NATS-proxy NamespaceCollection + four rbac metadata Collections + AclCache + invalidation subscribers). The proxy collections read through the platform broker's system.platform.rbac carve-out, so no direct DB credentials are needed. The registry is self-sufficient in any deployment with a reachable platform broker. Optional knobs:

  • THREETEARS_REGISTRY_ALLOW_ALL_TOOLS=true -- bypass the rbac stack entirely (dev only).
  • THREETEARS_REGISTRY_FORCE_DENY_ALL=true -- kill switch for misconfigured deployments.
  • THREETEARS_REGISTRY_ACL_TTL_SECONDS -- override the AclCache TTL (default 60s).

Dispatch flow:

sequenceDiagram
    participant Agent
    participant Registry
    participant RbacStack
    participant PlatformBroker
    participant ToolPod

    Agent->>Registry: ProxyCallRequest(tool_name, tool_version, context.user_id)
    Registry->>RbacStack: is_authorized(agent_id, user_id, tool_name, tool_version)
    RbacStack->>RbacStack: build_namespace_name(PLURAL_PREFIX_TOOL, tool_name, tool_version)
    RbacStack->>PlatformBroker: NamespaceCollection.get_by_name (system.platform.rbac proxy)
    PlatformBroker-->>RbacStack: tool namespace row
    RbacStack->>RbacStack: evaluate_decision (user ∩ agent grants)
    RbacStack-->>Registry: True / False
    Registry->>ToolPod: forward call (CallContext echoed)
    ToolPod-->>Registry: CallResponse
    Registry-->>Agent: ProxyCallResponse

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

3tears_registry-0.23.1.tar.gz (124.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

3tears_registry-0.23.1-py3-none-any.whl (76.6 kB view details)

Uploaded Python 3

File details

Details for the file 3tears_registry-0.23.1.tar.gz.

File metadata

  • Download URL: 3tears_registry-0.23.1.tar.gz
  • Upload date:
  • Size: 124.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for 3tears_registry-0.23.1.tar.gz
Algorithm Hash digest
SHA256 75fbaba0e2372ac938e6f2d3c23a88c9a473bbd9ac1fb65fda116cef158047fc
MD5 07710a3e43db1af2e20943ea31de898a
BLAKE2b-256 bdc8b11ffa34cdd8d5f33c56e1655e57bb8e7a1310e3af7a4402aa930abee8dd

See more details on using hashes here.

Provenance

The following attestation bundles were made for 3tears_registry-0.23.1.tar.gz:

Publisher: release.yml on pacepace/3tears

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file 3tears_registry-0.23.1-py3-none-any.whl.

File metadata

File hashes

Hashes for 3tears_registry-0.23.1-py3-none-any.whl
Algorithm Hash digest
SHA256 58d509e01b417cd39449ed55f512073330650f796e1e3cc14ef67237b48f13f3
MD5 11a16d2a426e2964b195670d9d614986
BLAKE2b-256 ef90d68c562f3780018ff7dee26acdd91d675b648fda6b22de50f13284bea018

See more details on using hashes here.

Provenance

The following attestation bundles were made for 3tears_registry-0.23.1-py3-none-any.whl:

Publisher: release.yml on pacepace/3tears

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.35.1

2 files

0.35.0

2 files

0.34.0

2 files

0.33.0

2 files

0.32.1

2 files

0.32.0

2 files

0.31.0

2 files

0.30.1

2 files

0.30.0

2 files

0.29.0

2 files

0.28.0

2 files

0.27.0

2 files

0.26.1

2 files

0.26.0

2 files

0.25.0

2 files

0.24.7

2 files

0.24.6

2 files

0.24.5

2 files

0.24.4

2 files

0.24.3

2 files

0.24.2

2 files

0.24.1

2 files

0.24.0

2 files

0.23.11

2 files

0.23.10

2 files

0.23.9

2 files

0.23.8

2 files

0.23.7

2 files

0.23.6

2 files

0.23.5

2 files

0.23.3

2 files

0.23.2

2 files

This release

0.23.1 This release

2 files

0.23.0

2 files

0.22.5

2 files

0.22.4

2 files

0.22.3

2 files

0.22.2

2 files

0.22.1

2 files

0.22.0

2 files

0.21.0

2 files

0.20.0

2 files

0.19.4

2 files

0.19.3

2 files

0.19.2

2 files

0.19.1

2 files

0.19.0

2 files

0.18.0

2 files

0.17.9

2 files

0.17.8

2 files

0.17.7

2 files

0.17.6

2 files

0.17.5

2 files

0.17.4

2 files

0.17.3

2 files

0.17.2

2 files

0.17.1

2 files

0.17.0

2 files

0.16.1

2 files

0.16.0

2 files

0.15.0

2 files

0.14.1

2 files

0.14.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page