Skip to main content

Available Registries

ToolRegistry

Manage MCP tools

ResourceRegistry

Manage resources and templates

PromptRegistry

Manage prompts

AgentRegistry

Manage agents

SkillRegistry

Manage skills

PluginRegistry

Manage plugins

HookRegistry

Manage flow hooks

ProviderRegistry

Manage DI providers

AuthRegistry

Manage auth providers

JobRegistry

Manage jobs

WorkflowRegistry

Manage workflows

Common Patterns

Lifecycle

All registries follow this lifecycle:
buildMap()     → Extract tokens, definitions from metadata
buildGraph()   → Validate dependencies, populate graph
initialize()   → Create instances, adopt from children

Indexing

Registries maintain indexes for O(1) lookups:
  • byQualifiedId: qualifiedId → entry
  • byName: baseName → entries[]
  • byOwnerAndName: “ownerKey:name” → entry
  • Registry-specific indexes (byUri, byId, etc.)

Change Events

All registries emit change events:
interface ChangeEvent {
  kind: 'added' | 'updated' | 'removed' | 'reset';
  changeScope: 'global' | 'session';
  version: number;
  snapshot: ReadonlyArray<Entry>;
  sessionId?: string;
  relatedRequestId?: string;
}
Subscribe to changes:
const unsubscribe = scope.tools.subscribe({}, (event) => {
  console.log(`Tool ${event.kind}:`, event);
});

Adoption

Registries adopt entries from child registries:
// Parent adopts child's tools
parentRegistry.adoptFromChild(childRegistry, owner);
  • References are shared (not cloned)
  • Lineage tracking for qualified names
  • Live updates via subscriptions

Export Name Resolution

Registries generate unique export names to avoid conflicts:
// Two apps with same tool name
app1/search'search' (no conflict)
app2/search'app2_search' (conflict resolved with prefix)

Capabilities

Registries expose MCP capabilities:
const caps = scope.tools.getCapabilities();
// { listChanged: true }

Accessing Registries

From Context Classes

@Tool({ name: 'my_tool', inputSchema: {} })
class MyTool extends ToolContext {
  async execute() {
    // Access via scope
    const tools = this.scope.tools;
    const resources = this.scope.resources;

    // List entries
    const allTools = tools.getTools();

    // Find specific entry
    const tool = tools.findByName('other_tool');
  }
}

From Scope

const scope = instance.getScopes()[0];

// All registries available
scope.tools;      // ToolRegistry
scope.resources;  // ResourceRegistry
scope.prompts;    // PromptRegistry
scope.agents;     // AgentRegistry
scope.skills;     // SkillRegistry
scope.plugins;    // PluginRegistry
scope.hooks;      // HookRegistry
scope.providers;  // ProviderRegistry
scope.auth;       // FrontMcpAuth (primary)
scope.authProviders; // AuthRegistry
scope.jobs;       // JobRegistry
scope.workflows;  // WorkflowRegistry

Common Methods

Most registries share these methods:

Listing

// Get all entries
registry.getTools();       // ToolRegistry
registry.getResources();   // ResourceRegistry
registry.getPrompts();     // PromptRegistry
registry.getAgents();      // AgentRegistry
registry.getSkills();      // SkillRegistry

Finding

// Find by name
registry.findByName('name');

// Find by qualified name
registry.findByQualifiedName('app:name');

// Check existence
registry.has('name');

Capabilities

// Get MCP capabilities
registry.getCapabilities();
// { listChanged: boolean, subscribe?: boolean, ... }

Subscriptions

// Subscribe to changes
const unsubscribe = registry.subscribe(
  { filter: (event) => event.kind === 'added' },
  (event) => console.log('Entry added:', event)
);

// Later
unsubscribe();

Owner Tracking

Each entry tracks its owner:
interface Owner {
  kind: 'scope' | 'app' | 'plugin' | 'adapter' | 'agent';
  id: string;
  ref?: Token;
}
Owners are used for:
  • Qualified name generation
  • Lineage tracking
  • Access control

Lineage System

Entries track their lineage (chain of owners):
// Tool in: scope → app → plugin
const tool = registry.findByName('tool');
console.log(tool.lineage);
// [
//   { kind: 'scope', id: 'main' },
//   { kind: 'app', id: 'my-app' },
//   { kind: 'plugin', id: 'my-plugin' },
// ]
Used for:
  • Generating qualified names
  • Preventing double-prefixing
  • Debugging ownership