Skip to main content

Class Definition

export abstract class SkillContext extends ExecutionContextBase<SkillContent>

Properties

PropertyTypeDescription
metadataSkillMetadataSkill metadata
skillNamestringSkill name
skillIdstringSkill ID

Abstract Methods

loadInstructions()

Load skill instructions from the configured source.
abstract loadInstructions(): Promise<string>
Instructions can come from:
  • Inline string
  • File reference ({ file: './path.md' })
  • URL reference ({ url: 'https://...' })

build()

Build the complete skill content.
abstract build(): Promise<SkillContent>

SkillContent Interface

interface SkillContent {
  id: string;
  name: string;
  description: string;
  instructions: string;
  tools: Array<{
    name: string;
    purpose?: string;
    required?: boolean;
  }>;
  parameters?: SkillParameter[];
  examples?: SkillExample[];

  // Agent Skills spec fields
  license?: string;
  compatibility?: string;
  specMetadata?: Record<string, string>;
  allowedTools?: string;
  resources?: SkillResources;
}

interface SkillResources {
  scripts?: string;    // Path to scripts directory
  references?: string; // Path to references directory
  assets?: string;     // Path to assets directory
}

Methods

getToolRefs()

Get normalized tool references from metadata.
getToolRefs(): SkillToolRef[]
interface SkillToolRef {
  name: string;
  purpose?: string;
  required?: boolean;
}

getToolNames()

Get tool names from metadata.
getToolNames(): string[]

Basic Example

import { Skill, SkillContext } from '@frontmcp/sdk';

@Skill({
  name: 'data-analysis',
  description: 'Analyze datasets and generate insights',
  instructions: `
# Data Analysis Workflow

1. Load the dataset using query_database
2. Analyze patterns and trends
3. Generate visualizations with create_chart
4. Summarize findings
  `,
  tools: ['query_database', 'create_chart'],
})
class DataAnalysisSkill extends SkillContext {
  async loadInstructions() {
    // Return inline instructions
    return this.metadata.instructions as string;
  }

  async build() {
    return {
      id: this.skillId,
      name: this.metadata.name,
      description: this.metadata.description,
      instructions: await this.loadInstructions(),
      tools: this.getToolRefs().map(ref => ({
        name: ref.name,
        purpose: ref.purpose,
        required: ref.required !== false,
      })),
    };
  }
}

File-Based Instructions

import { Skill, SkillContext } from '@frontmcp/sdk';
import { readFile } from '@frontmcp/utils';
import { resolve } from 'path';

@Skill({
  name: 'code-review',
  description: 'Code review workflow',
  instructions: { file: './skills/code-review.md' },
  tools: ['github_get_pr', 'github_comment'],
})
class CodeReviewSkill extends SkillContext {
  async loadInstructions() {
    const source = this.metadata.instructions;

    if (typeof source === 'string') {
      return source;
    }

    if ('file' in source) {
      const filePath = resolve(process.cwd(), source.file);
      return readFile(filePath, 'utf-8');
    }

    throw new Error('Unknown instruction source');
  }

  async build() {
    return {
      id: this.skillId,
      name: this.metadata.name,
      description: this.metadata.description,
      instructions: await this.loadInstructions(),
      tools: this.getToolRefs().map(ref => ({
        name: ref.name,
        purpose: ref.purpose,
        required: ref.required !== false,
      })),
      parameters: this.metadata.parameters,
      examples: this.metadata.examples,
    };
  }
}

URL-Based Instructions

import { Skill, SkillContext } from '@frontmcp/sdk';

@Skill({
  name: 'api-integration',
  description: 'API integration workflow',
  instructions: { url: 'https://docs.example.com/skills/api-integration.md' },
  tools: ['http_request', 'parse_json'],
})
class ApiIntegrationSkill extends SkillContext {
  async loadInstructions() {
    const source = this.metadata.instructions;

    if (typeof source === 'string') {
      return source;
    }

    if ('url' in source) {
      const response = await this.fetch(source.url);
      if (!response.ok) {
        throw new Error(`Failed to fetch instructions: ${response.status}`);
      }
      return response.text();
    }

    if ('file' in source) {
      // Handle file...
    }

    throw new Error('Unknown instruction source');
  }

  async build() {
    return {
      id: this.skillId,
      name: this.metadata.name,
      description: this.metadata.description,
      instructions: await this.loadInstructions(),
      tools: this.getToolRefs().map(ref => ({
        name: ref.name,
        purpose: ref.purpose,
        required: ref.required !== false,
      })),
    };
  }
}

With Parameters and Examples

import { Skill, SkillContext } from '@frontmcp/sdk';

@Skill({
  name: 'deploy-application',
  description: 'Deploy applications to cloud environments',
  instructions: `
# Deployment Workflow

## Prerequisites
- Ensure all tests pass
- Verify configuration

## Steps
1. Build the application
2. Run smoke tests
3. Deploy to target environment
4. Verify deployment
5. Notify team
  `,
  tools: [
    { name: 'build_app', purpose: 'Build the application', required: true },
    { name: 'run_tests', purpose: 'Execute test suite', required: true },
    { name: 'deploy', purpose: 'Deploy to environment', required: true },
    { name: 'health_check', purpose: 'Verify deployment health', required: true },
    { name: 'notify_slack', purpose: 'Send notifications', required: false },
  ],
  parameters: [
    {
      name: 'environment',
      description: 'Target deployment environment',
      required: true,
      type: 'string',
    },
    {
      name: 'version',
      description: 'Version to deploy',
      required: false,
      type: 'string',
      default: 'latest',
    },
    {
      name: 'notifyChannel',
      description: 'Slack channel for notifications',
      required: false,
      type: 'string',
    },
  ],
  examples: [
    {
      scenario: 'Deploy to staging',
      parameters: { environment: 'staging', version: 'v1.2.3' },
      expectedOutcome: 'Application deployed to staging environment',
    },
    {
      scenario: 'Deploy to production with notification',
      parameters: {
        environment: 'production',
        version: 'v1.2.3',
        notifyChannel: '#deployments',
      },
      expectedOutcome: 'Application deployed to production, team notified',
    },
  ],
  tags: ['devops', 'deployment', 'ci-cd'],
  priority: 5,
})
class DeployApplicationSkill extends SkillContext {
  async loadInstructions() {
    return this.metadata.instructions as string;
  }

  async build() {
    const instructions = await this.loadInstructions();

    return {
      id: this.skillId,
      name: this.metadata.name,
      description: this.metadata.description,
      instructions,
      tools: this.getToolRefs().map(ref => ({
        name: ref.name,
        purpose: ref.purpose,
        required: ref.required !== false,
      })),
      parameters: this.metadata.parameters,
      examples: this.metadata.examples,
    };
  }
}

Full Example

import { Skill, SkillContext, Tool, ToolContext, App, FrontMcp } from '@frontmcp/sdk';
import { z } from 'zod';
import { readFile } from '@frontmcp/utils';
import { resolve } from 'path';

// Tools
@Tool({
  name: 'jira_get_sprint',
  inputSchema: { sprintId: z.string() },
})
class JiraGetSprintTool extends ToolContext {
  async execute(input) {
    return { sprintId: input.sprintId, name: 'Sprint 23', issues: [] };
  }
}

@Tool({
  name: 'jira_create_issue',
  inputSchema: { title: z.string(), description: z.string() },
})
class JiraCreateIssueTool extends ToolContext {
  async execute(input) {
    return { issueKey: 'PROJ-123', title: input.title };
  }
}

@Tool({
  name: 'confluence_create_page',
  inputSchema: { title: z.string(), content: z.string() },
})
class ConfluenceCreatePageTool extends ToolContext {
  async execute(input) {
    return { pageId: 'page-123', url: 'https://...' };
  }
}

// Skill
@Skill({
  name: 'sprint-retrospective',
  description: 'Conduct and document sprint retrospectives',
  instructions: { file: './skills/sprint-retro.md' },
  tools: [
    { name: 'jira_get_sprint', purpose: 'Get sprint details and issues', required: true },
    { name: 'confluence_create_page', purpose: 'Document retrospective notes', required: true },
    { name: 'jira_create_issue', purpose: 'Create improvement tickets', required: false },
  ],
  parameters: [
    { name: 'sprintId', description: 'Sprint to retrospect', required: true, type: 'string' },
    { name: 'teamName', description: 'Team name', required: true, type: 'string' },
  ],
  examples: [
    {
      scenario: 'Run retrospective for completed sprint',
      parameters: { sprintId: 'sprint-23', teamName: 'Platform Team' },
      expectedOutcome: 'Retrospective documented, improvement issues created',
    },
  ],
  tags: ['agile', 'retrospective', 'jira', 'confluence'],
})
class SprintRetrospectiveSkill extends SkillContext {
  async loadInstructions() {
    const source = this.metadata.instructions;

    if (typeof source === 'string') {
      return source;
    }

    if ('file' in source) {
      try {
        const filePath = resolve(process.cwd(), source.file);
        return await readFile(filePath, 'utf-8');
      } catch (error) {
        this.logger.warn('Failed to load instructions from file, using fallback');
        return this.getFallbackInstructions();
      }
    }

    if ('url' in source) {
      const response = await this.fetch(source.url);
      if (!response.ok) {
        this.logger.warn('Failed to fetch instructions from URL, using fallback');
        return this.getFallbackInstructions();
      }
      return response.text();
    }

    return this.getFallbackInstructions();
  }

  private getFallbackInstructions(): string {
    return `
# Sprint Retrospective Workflow

1. Get sprint details using jira_get_sprint
2. Review completed and incomplete issues
3. Gather team feedback on:
   - What went well
   - What could be improved
   - Action items
4. Document in Confluence using confluence_create_page
5. Create improvement issues in Jira if needed
    `;
  }

  async build() {
    this.mark('loading-instructions');
    const instructions = await this.loadInstructions();

    this.mark('building-content');
    return {
      id: this.skillId,
      name: this.metadata.name,
      description: this.metadata.description,
      instructions,
      tools: this.getToolRefs().map(ref => ({
        name: ref.name,
        purpose: ref.purpose,
        required: ref.required !== false,
      })),
      parameters: this.metadata.parameters,
      examples: this.metadata.examples,
    };
  }
}

@App({
  name: 'agile-tools',
  tools: [JiraGetSprintTool, JiraCreateIssueTool, ConfluenceCreatePageTool],
  skills: [SprintRetrospectiveSkill],
})
class AgileToolsApp {}

@FrontMcp({
  info: { name: 'Agile Assistant', version: '1.0.0' },
  apps: [AgileToolsApp],
  skillsConfig: {
    enabled: true,
    validation: 'strict',
  },
})
export default class AgileServer {}

@Skill

Skill decorator

SkillRegistry

Skill registry

Skills Overview

Skills documentation

@Tool

Tool decorator