Skip to main content

Overview

import { SkillRegistry } from '@frontmcp/sdk';

// Access via scope
const skills = scope.skills;

// List all skills
const allSkills = skills.getSkills();

// Search skills
const results = await skills.search('data analysis');

// Load a skill
const skill = await skills.loadSkill('data-pipeline');

Methods

getSkills()

Get all skills with optional filtering.
getSkills(options?: GetSkillsOptions): ReadonlyArray<SkillEntry>
OptionTypeDescription
includeHiddenbooleanInclude hidden skills
visibility'mcp' | 'http' | 'both'Filter by visibility
Example:
// Get all visible skills
const skills = registry.getSkills();

// Get skills visible via HTTP
const httpSkills = registry.getSkills({ visibility: 'http' });
Search skills using TF-IDF text matching.
search(query: string, options?: SearchOptions): Promise<SearchResult[]>
OptionTypeDescription
limitnumberMaximum results to return
minScorenumberMinimum relevance score
visibility'mcp' | 'http' | 'both'Filter by visibility
Example:
const results = await registry.search('data analysis', {
  limit: 10,
  minScore: 0.5,
});

for (const result of results) {
  console.log(`${result.skill.name}: ${result.score}`);
}

loadSkill()

Load skill content by ID/name with tool validation.
loadSkill(skillId: string): Promise<LoadedSkill>
Example:
const skill = await registry.loadSkill('data-pipeline');
console.log(skill.content); // Full skill content
console.log(skill.tools);   // Validated tool references

listSkills()

List skills with pagination support.
listSkills(options?: ListOptions): Promise<SkillListResult>
OptionTypeDescription
offsetnumberStarting index
limitnumberMaximum results
visibility'mcp' | 'http' | 'both'Filter by visibility
Example:
const page = await registry.listSkills({
  offset: 0,
  limit: 20,
});

console.log(`Total: ${page.total}`);
console.log(`Skills: ${page.items.length}`);

count()

Get total skill count.
count(options?: CountOptions): Promise<number>

findByName()

Find a skill by its base name.
findByName(name: string): SkillEntry | undefined

findByQualifiedName()

Find a skill by its fully qualified name.
findByQualifiedName(qualifiedName: string): SkillEntry | undefined

getInlineSkills()

Get skills defined inline (local only).
getInlineSkills(): ReadonlyArray<SkillEntry>

validateAllTools()

Validate all skills’ tool references against the ToolRegistry.
validateAllTools(): ValidationResult
Example:
const result = registry.validateAllTools();
if (!result.valid) {
  for (const error of result.errors) {
    console.error(`${error.skill}: Missing tool ${error.tool}`);
  }
}

subscribe()

Subscribe to skill change events.
subscribe(
  opts: SubscribeOptions,
  cb: (event: SkillChangeEvent) => void
): () => void
Returns: Unsubscribe function.

getCapabilities()

Get MCP capabilities for skills.
getCapabilities(): { listChanged: boolean }

hasAny()

Check if any skills exist.
hasAny(): boolean

adoptFromChild()

Adopt skills from a child registry.
adoptFromChild(child: SkillRegistry, childOwner: Owner): void

External Storage

Skills can be synced to external storage for persistence:

setExternalProvider()

Configure an external storage provider.
setExternalProvider(provider: ExternalSkillProviderBase): void

syncToExternal()

Sync local skills to external storage.
syncToExternal(): Promise<SyncResult>
Example:
// Configure Redis-based storage
registry.setExternalProvider(new RedisSkillProvider(redisClient));

// Sync skills
const result = await registry.syncToExternal();
console.log(`Synced ${result.count} skills`);

hasExternalProvider()

Check if external provider is configured.
hasExternalProvider(): boolean

getExternalProvider()

Get the configured external provider.
getExternalProvider(): ExternalSkillProviderBase | undefined

Change Events

interface SkillChangeEvent {
  kind: 'added' | 'updated' | 'removed' | 'reset';
  changeScope: 'global' | 'session';
  version: number;
  snapshot: ReadonlyArray<SkillEntry>;
  entry?: SkillEntry;
  sessionId?: string;
  relatedRequestId?: string;
}

SkillEntry Accessors

Each skill in the registry is a SkillEntry with these accessor methods:
MethodReturn TypeDescription
getDescription()stringSkill description
getToolRefs()SkillToolRef[]Normalized tool references
getToolNames()string[]Tool name strings
getTags()string[]Categorization tags
getPriority()numberSearch ranking priority
isHidden()booleanWhether hidden from discovery
getLicense()string | undefinedLicense (per Agent Skills spec)
getCompatibility()string | undefinedCompatibility notes (per Agent Skills spec)
getSpecMetadata()Record<string, string> | undefinedArbitrary metadata (per Agent Skills spec)
getAllowedTools()string | undefinedPre-approved tools (per Agent Skills spec)
getResources()SkillResources | undefinedBundled resource directories
const skill = registry.findByName('review-pr');
if (skill) {
  console.log(skill.getLicense());       // 'MIT'
  console.log(skill.getCompatibility()); // 'Requires git CLI'
  console.log(skill.getResources());     // { scripts: '...', references: '...' }
}

Skill Visibility

Skills can have different visibility modes:
VisibilityDescription
mcpAvailable only via MCP protocol
httpAvailable only via HTTP API
bothAvailable via both MCP and HTTP
@Skill({
  name: 'internal-task',
  visibility: 'mcp', // Only for MCP clients
})
class InternalTask extends SkillContext { }

@Skill({
  name: 'public-api',
  visibility: 'http', // Only for HTTP clients
})
class PublicAPI extends SkillContext { }

Tool Validation

Skills can reference tools that must exist in the registry:
@Skill({
  name: 'data-pipeline',
  tools: ['fetch_data', 'transform', 'save_results'],
})
class DataPipeline extends SkillContext { }
Validation modes:
  • strict: Fail if any tool is missing
  • warn: Log warning for missing tools
  • ignore: Skip validation