Skip to main content

Custom Tool Development for LLM-MCP

This comprehensive guide covers the process of developing, testing, and deploying custom tools for the LLM Platform Model Context Protocol (LLM-MCP). Custom tools extend the platform's capabilities by providing specialized functionality that can be orchestrated through the LLM-MCP server.

Table of Contentsโ€‹

Introductionโ€‹

What are LLM-MCP Tools?โ€‹

LLM-MCP tools are modular, reusable components that provide specific functionality that can be invoked by AI models or other services. Tools can perform a wide range of actions, from simple data retrieval to complex data processing and external API interactions.

Types of Toolsโ€‹

  1. System Tools: Core tools provided by LLM-MCP for basic operations
  2. Integration Tools: Tools that integrate with other services
  3. Custom Tools: User-developed tools for specialized functionality
  4. Composite Tools: Tools that combine multiple tools into workflows

Tool Capabilitiesโ€‹

LLM-MCP tools can:

  • Access external APIs and services
  • Process and transform data
  • Interact with databases and vector stores
  • Execute code in controlled environments
  • Provide UI interactions
  • Implement complex business logic

Tool Architectureโ€‹

Tool Component Structureโ€‹

graph TD;
A[Tool Definition] --> B[Tool Schema];
A --> C[Tool Handler];
A --> D[Tool Configuration];
B --> E[Input Schema];
B --> F[Output Schema];
C --> G[Execute Method];
C --> H[Validation Logic];
D --> I[Default Parameters];
D --> J[Resource Limits];

Core Componentsโ€‹

  1. Tool Definition: Metadata about the tool
  2. Tool Schema: Definition of inputs and outputs
  3. Tool Handler: Implementation of tool functionality
  4. Tool Configuration: Settings and parameters

Tool Interfaceโ€‹

All tools must implement the McpTool interface:

interface McpTool {
name: string;
description: string;
version: string;
schema: ToolSchema;
execute(params: any): Promise<any>;
validate?(params: any): boolean | Promise<boolean>;
}

interface ToolSchema {
input: JSONSchema;
output: JSONSchema;
}

Tool Development Lifecycleโ€‹

The typical development lifecycle for a custom LLM-MCP tool includes:

  1. Planning: Define the tool's purpose and capabilities
  2. Development: Implement the tool functionality
  3. Testing: Unit and integration testing
  4. Registration: Register the tool with LLM-MCP
  5. Deployment: Deploy the tool in production
  6. Monitoring: Monitor tool usage and performance
  7. Updates: Update the tool as needed

Creating a Basic Toolโ€‹

Step 1: Create Tool Definitionโ€‹

Create a new file for your tool (e.g., my-custom-tool.ts):

import { McpTool, ToolSchema } from '@llm-mcp/tool-sdk';

export class MyCustomTool implements McpTool {
name = 'my-custom-tool';
description = 'A custom tool that performs a specific function';
version = '1.0.0';

schema: ToolSchema = {
input: {
type: 'object',
properties: {
param1: {
type: 'string',
description: 'First parameter description'
},
param2: {
type: 'number',
description: 'Second parameter description'
}
},
required: ['param1']
},
output: {
type: 'object',
properties: {
result: {
type: 'string',
description: 'Result description'
}
}
}
};

async execute(params: any): Promise<any> {
// Implement your tool functionality here
const { param1, param2 = 0 } = params;

// Example processing
const result = `Processed [param1] with value [param2]`;

return [result];
}

validate(params: any): boolean {
// Optional validation beyond schema validation
if (params.param2 && params.param2 < 0) {
return false;
}
return true;
}
}

Step 2: Test Your Toolโ€‹

Create a test file for your tool (e.g., my-custom-tool.test.ts):

import [MyCustomTool] from './my-custom-tool';

describe('MyCustomTool', () => {
let tool: MyCustomTool;

beforeEach(() => {
tool = new MyCustomTool();
});

test('should have correct metadata', () => {
expect(tool.name).toBe('my-custom-tool');
expect(tool.version).toBe('1.0.0');
expect(tool.description).toBeDefined();
});

test('should have valid schema', () => {
expect(tool.schema.input).toBeDefined();
expect(tool.schema.output).toBeDefined();
});

test('should execute successfully with valid parameters', async () => {
const result = await tool.execute({ param1: 'test', param2: 5 });
expect(result).toHaveProperty('result');
expect(result.result).toContain('test');
expect(result.result).toContain('5');
});

test('should execute successfully with only required parameters', async () => {
const result = await tool.execute({ param1: 'test' });
expect(result).toHaveProperty('result');
});

test('validation should reject negative param2', () => {
expect(tool.validate({ param1: 'test', param2: -5 })).toBe(false);
expect(tool.validate({ param1: 'test', param2: 5 })).toBe(true);
});
});

Step 3: Register Your Toolโ€‹

Register your tool with LLM-MCP:

import [McpClient] from '@llm-mcp/client';
import [MyCustomTool] from './my-custom-tool';

async function registerTool() {
const client = new McpClient({
url: 'http://localhost:3001',
apiKey: 'your-api-key'
});

const tool = new MyCustomTool();

try {
const registrationResult = await client.registerTool(tool);
console.log('Tool registered successfully:', registrationResult);
} catch (error) {
console.error('Failed to register tool:', error);
}
}

registerTool();

Advanced Tool Developmentโ€‹

Using External Servicesโ€‹

Tools often need to interact with external services:

import axios from 'axios';
import { McpTool, ToolSchema } from '@llm-mcp/tool-sdk';

export class WeatherTool implements McpTool {
name = 'weather-tool';
description = 'Get current weather for a location';
version = '1.0.0';

schema: ToolSchema = {
input: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'City name or zip code'
}
},
required: ['location']
},
output: {
type: 'object',
properties: {
temperature: {
type: 'number',
description: 'Current temperature in Celsius'
},
conditions: {
type: 'string',
description: 'Weather conditions'
}
}
}
};

async execute(params: any): Promise<any> [const { location] = params;

try {
// Replace with your actual weather API
const response = await axios.get(
`https://api.weather.example.com/current?location=[encodeURIComponent(location)]`,
{
headers: {
'Authorization': `Bearer [process.env.WEATHER_API_KEY]`
}
}
);

return {
temperature: response.data.temperature,
conditions: response.data.conditions
};
} catch (error) {
throw new Error(`Failed to get weather data: [error.message]`);
}
}
}

Handling Authenticationโ€‹

For tools that require authentication:

import { McpTool, ToolSchema, ToolAuth } from '@llm-mcp/tool-sdk';

export class AuthenticatedTool implements McpTool {
name = 'authenticated-tool';
description = 'Tool that requires authentication';
version = '1.0.0';

// Define authentication requirements
auth: ToolAuth = {
type: 'oauth2',
description: 'Authentication required for ExampleService',
scopes: ['read', 'write']
};

schema: ToolSchema = [// Schema definition...];

async execute(params: any, context: any): Promise<any> [// The context object contains authentication information
const { auth] = context;

if (!auth || !auth.token) {
throw new Error('Authentication required');
}

// Use auth.token for authenticated requests
// ...

return { result: 'Authenticated operation completed' };
}
}

Stateful Toolsโ€‹

For tools that need to maintain state:

import { McpTool, ToolSchema } from '@llm-mcp/tool-sdk';

export class CounterTool implements McpTool {
name = 'counter-tool';
description = 'Maintains a counter state';
version = '1.0.0';

private counters: Map<string, number> = new Map();

schema: ToolSchema = {
input: {
type: 'object',
properties: {
counterId: {
type: 'string',
description: 'Unique counter ID'
},
operation: {
type: 'string',
enum: ['increment', 'decrement', 'reset', 'get'],
description: 'Operation to perform'
}
},
required: ['counterId', 'operation']
},
output: {
type: 'object',
properties: {
value: {
type: 'number',
description: 'Current counter value'
}
}
}
};

async execute(params: any): Promise<any> {
const { counterId, operation } = params;

if (!this.counters.has(counterId)) {
this.counters.set(counterId, 0);
}

let value = this.counters.get(counterId);

switch (operation) {
case 'increment':
value++;
break;
case 'decrement':
value--;
break;
case 'reset':
value = 0;
break;
case 'get':
// Just return current value
break;
default:
throw new Error(`Unknown operation: [operation]`);
}

this.counters.set(counterId, value);

return Value;
}
}

Vector Operationsโ€‹

For tools that work with vector embeddings:

import { McpTool, ToolSchema } from '@llm-mcp/tool-sdk';
import [VectorService] from '@llm-mcp/vector-service';

export class VectorSearchTool implements McpTool {
name = 'vector-search-tool';
description = 'Search for similar vectors';
version = '1.0.0';

private vectorService: VectorService;

constructor() {
this.vectorService = new VectorService({
// Vector service configuration
});
}

schema: ToolSchema = {
input: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'Query text to search for'
},
collection: {
type: 'string',
description: 'Vector collection name'
},
limit: {
type: 'number',
description: 'Maximum number of results',
default: 5
}
},
required: ['query', 'collection']
},
output: {
type: 'object',
properties: {
results: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'string' },
score: { type: 'number' },
metadata: { type: 'object' }
}
},
description: 'Search results'
}
}
}
};

async execute(params: any): Promise<any> {
const { query, collection, limit = 5 } = params;

// Get vector embedding for the query
const embedding = await this.vectorService.getEmbedding(query);

// Search for similar vectors
const results = await this.vectorService.search({
collection,
vector: embedding,
limit
});

return [results];
}
}

Tool Testingโ€‹

Unit Testingโ€‹

Basic unit testing for tools:

import [MyCustomTool] from './my-custom-tool';
import [mockExternalService] from './test-utils';

// Mock external dependencies
jest.mock('axios');

describe('MyCustomTool', () => {
let tool: MyCustomTool;

beforeEach(() => {
tool = new MyCustomTool();
mockExternalService();
});

// Test cases...
});

Integration Testingโ€‹

Testing tool integration with LLM-MCP:

import [McpClient] from '@llm-mcp/client';
import [MyCustomTool] from './my-custom-tool';

describe('MyCustomTool Integration', () => {
let client: McpClient;
let tool: MyCustomTool;

beforeAll(async () => {
// Set up a test LLM-MCP instance
client = new McpClient({
url: 'http://localhost:3001',
apiKey: 'test-api-key'
});

tool = new MyCustomTool();

// Register tool for testing
await client.registerTool(tool);
});

test('should execute tool through MCP', async () => {
const result = await client.executeTool('my-custom-tool', {
param1: 'test',
param2: 5
});

expect(result).toHaveProperty('result');
expect(result.result).toContain('test');
});

afterAll(async () => {
// Clean up
await client.unregisterTool('my-custom-tool');
});
});

Performance Testingโ€‹

Testing tool performance:

import [MyCustomTool] from './my-custom-tool';

describe('MyCustomTool Performance', () => {
let tool: MyCustomTool;

beforeEach(() => {
tool = new MyCustomTool();
});

test('should execute within time limit', async () => {
const start = Date.now();

await tool.execute({ param1: 'test', param2: 5 });

const duration = Date.now() - start;
expect(duration).toBeLessThan(100); // Should execute in less than 100ms
});

test('should handle concurrent executions', async () => {
const executions = Array(100).fill(null).map((_, i) =>
tool.execute({ param1: `test-[i]`, param2: i })
);

const results = await Promise.all(executions);

expect(results.length).toBe(100);
results.forEach((result, i) => {
expect(result.result).toContain(`test-[i]`);
});
});
});

Tool Registrationโ€‹

Automatic Registrationโ€‹

Register tools automatically at startup:

import [McpClient] from '@llm-mcp/client';
import [ToolA] from './tools/tool-a';
import [ToolB] from './tools/tool-b';
import [ToolC] from './tools/tool-c';

async function registerTools() {
const client = new McpClient({
url: process.env.LLM-MCP_URL,
apiKey: process.env.LLM-MCP_API_KEY
});

const tools = [
new ToolA(),
new ToolB(),
new ToolC()
];

for (const tool of tools) {
try {
await client.registerTool(tool);
console.log(`Registered tool: [tool.name]`);
} catch (error) {
console.error(`Failed to register tool [tool.name]:`, error);
}
}
}

registerTools();

Dynamic Tool Registrationโ€‹

Register tools dynamically based on configuration:

import [McpClient] from '@llm-mcp/client';
import * as fs from 'fs';
import * as path from 'path';

async function loadAndRegisterTools() {
const client = new McpClient({
url: process.env.LLM-MCP_URL,
apiKey: process.env.LLM-MCP_API_KEY
});

// Load tool configuration
const config = JSON.parse(
fs.readFileSync(path.join(__dirname, 'tool-config.json'), 'utf8')
);

for (const toolConfig of config.tools) {
if (!toolConfig.enabled) continue;

try {
// Dynamically import tool module
const ToolClass = require(`./tools/[toolConfig.file]`).default;
const tool = new ToolClass(toolConfig.options);

await client.registerTool(tool);
console.log(`Registered tool: [tool.name]`);
} catch (error) {
console.error(`Failed to register tool [toolConfig.name]:`, error);
}
}
}

loadAndRegisterTools();

Tool Deploymentโ€‹

Standalone Tool Serviceโ€‹

Deploy tools as a standalone service:

import express from 'express';
import [McpClient] from '@llm-mcp/client';
import [ToolA] from './tools/tool-a';
import [ToolB] from './tools/tool-b';

async function startToolService() {
const app = express();
const port = process.env.PORT || 3000;

const client = new McpClient({
url: process.env.LLM-MCP_URL,
apiKey: process.env.LLM-MCP_API_KEY
});

const tools = [
new ToolA(),
new ToolB()
];

// Register all tools
for (const tool of tools) {
await client.registerTool(tool);
console.log(`Registered tool: [tool.name]`);
}

// Health check endpoint
app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok' });
});

// Start server
app.listen(port, () => {
console.log(`Tool service running on port 3000`);
});

// Handle graceful shutdown
process.on('SIGTERM', async () => {
console.log('Shutting down...');
for (const tool of tools) {
await client.unregisterTool(tool.name);
console.log(`Unregistered tool: [tool.name]`);
}
process.exit(0);
});
}

startToolService();

Container Deploymentโ€‹

Docker configuration for tool deployment:

FROM node:18-alpine

WORKDIR /app

# Copy package files
COPY package*.json ./
RUN npm ci --only=production

# Copy application code
COPY . .

# Set environment variables
ENV NODE_ENV=production
ENV LLM-MCP_URL=http://llm-mcp:3001

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD wget -qO- http://localhost:3000/health || exit 1

# Start the service
CMD ["node", "src/index.js"]

Kubernetes Deploymentโ€‹

Kubernetes configuration for tool deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
name: custom-tools
labels:
app: custom-tools
spec:
replicas: 2
selector:
matchLabels:
app: custom-tools
template:
metadata:
labels:
app: custom-tools
spec:
containers:
- name: custom-tools
image: your-registry/custom-tools:latest
ports:
- containerPort: 3000
env:
- name: LLM-MCP_URL
value: "http://llm-mcp-service:3001"
- name: LLM-MCP_API_KEY
valueFrom:
secretKeyRef:
name: llm-mcp-credentials
key: api-key
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "100m"
memory: "128Mi"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 30

Tool Versioningโ€‹

Versioning Strategyโ€‹

Implement proper versioning for your tools:

import { McpTool, ToolSchema } from '@llm-mcp/tool-sdk';

export class VersionedTool implements McpTool {
name = 'versioned-tool';
description = 'Tool with proper versioning';
version = '2.0.0'; // Major version change indicates breaking changes

// Support previous version
aliases = ['versioned-tool@1']; // Allow explicit version reference

schema: ToolSchema = {
// Current schema version
input: {
type: 'object',
properties: {
newParam: { type: 'string' } // New parameter in v2
}
},
output: {
type: 'object',
properties: {
result: { type: 'string' }
}
}
};

// Schema for v1 compatibility
legacySchemas = {
'1': {
input: {
type: 'object',
properties: {
oldParam: { type: 'string' } // Old parameter in v1
}
},
output: {
type: 'object',
properties: {
result: { type: 'string' }
}
}
}
};

async execute(params: any, context: any): Promise<any> {
// Check if using legacy version
const requestedVersion = context.requestedVersion || this.version;

if (requestedVersion.startsWith('1.')) {
// Handle v1 request format
const { oldParam } = params;
return { result: `Legacy result with [oldParam]` };
}

// Handle current version
const [newParam] = params;
return { result: `New result with [newParam]` };
}
}

Version Migrationโ€‹

Guide for migrating between tool versions:

  1. Add version compatibility: Support older versions while introducing new ones
  2. Deprecation notices: Clearly mark deprecated versions
  3. Migration guide: Provide clear documentation for migration
  4. Testing: Test all supported versions

Best Practicesโ€‹

Development Best Practicesโ€‹

  1. Clear purpose: Each tool should have a single, well-defined purpose
  2. Input validation: Validate all inputs thoroughly
  3. Error handling: Handle errors gracefully and provide clear error messages
  4. Documentation: Document the tool's purpose, inputs, outputs, and behavior
  5. Testing: Write comprehensive tests for your tools
  6. Performance: Optimize for performance, especially for frequently used tools
  7. Security: Follow security best practices, especially for tools that access external services
  8. Statelessness: Prefer stateless tools when possible for easier scaling
  9. Idempotency: Ensure operations are idempotent when appropriate
  10. Versioning: Use semantic versioning for your tools

Security Best Practicesโ€‹

  1. Input sanitization: Sanitize all inputs to prevent injection attacks
  2. Credential management: Never hardcode credentials
  3. Principle of least privilege: Request only the permissions you need
  4. Resource limits: Implement resource limits to prevent abuse
  5. Secure dependencies: Keep dependencies updated and scan for vulnerabilities

Performance Best Practicesโ€‹

  1. Minimize external calls: Reduce the number of external API calls
  2. Implement caching: Cache results when appropriate
  3. Connection pooling: Use connection pooling for database connections
  4. Asynchronous operations: Use asynchronous operations for I/O-bound tasks
  5. Resource cleanup: Properly close connections and free resources

Troubleshootingโ€‹

Common Issuesโ€‹

  1. Tool registration fails:

    • Check that the tool implements the McpTool interface correctly
    • Verify that the tool name is unique
    • Check for network connectivity issues
  2. Tool execution fails:

    • Check input validation
    • Verify external service availability
    • Check for permission issues
  3. Performance issues:

    • Look for blocking operations
    • Check for memory leaks
    • Monitor external service performance

Debugging Toolsโ€‹

import { McpTool, ToolSchema } from '@llm-mcp/tool-sdk';
import * as fs from 'fs';

export class DebugTool implements McpTool {
name = 'debug-tool';
description = 'Tool for debugging purposes';
version = '1.0.0';

schema: ToolSchema = {
// Schema definition...
};

async execute(params: any, context: any): Promise<any> {
// Log execution details for debugging
const debugInfo = {
timestamp: new Date().toISOString(),
params,
context,
environment: process.env
};

// Write to debug log
fs.appendFileSync(
'debug-logs.json',
JSON.stringify(debugInfo, null, 2) + ',\n'
);

// Continue with normal execution
// ...

return { result: 'Debug information logged' };
}
}

Examplesโ€‹

Web API Integration Toolโ€‹

import { McpTool, ToolSchema } from '@llm-mcp/tool-sdk';
import axios from 'axios';

export class WeatherApiTool implements McpTool {
name = 'weather-api-tool';
description = 'Get weather information for a location';
version = '1.0.0';

schema: ToolSchema = {
input: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'City name or zip code'
},
units: {
type: 'string',
enum: ['metric', 'imperial'],
default: 'metric',
description: 'Units for temperature (metric = Celsius, imperial = Fahrenheit)'
}
},
required: ['location']
},
output: {
type: 'object',
properties: {
temperature: {
type: 'number',
description: 'Current temperature'
},
conditions: {
type: 'string',
description: 'Weather conditions'
},
humidity: {
type: 'number',
description: 'Humidity percentage'
},
windSpeed: {
type: 'number',
description: 'Wind speed'
}
}
}
};

async execute(params: any): Promise<any> {
const { location, units = 'metric' } = params;

try {
const response = await axios.get(
'https://api.weather.example.com/current',
{
params: {
location,
units
},
headers: {
'Authorization': `Bearer [process.env.WEATHER_API_KEY]`
}
}
);

return {
temperature: response.data.current.temperature,
conditions: response.data.current.conditions,
humidity: response.data.current.humidity,
windSpeed: response.data.current.wind_speed
};
} catch (error) {
throw new Error(`Weather API error: [error.message]`);
}
}
}

Database Integration Toolโ€‹

import { McpTool, ToolSchema } from '@llm-mcp/tool-sdk';
import [Pool] from 'pg';

export class DatabaseQueryTool implements McpTool {
name = 'database-query-tool';
description = 'Execute predefined database queries';
version = '1.0.0';

private pool: Pool;

constructor() {
this.pool = new Pool({
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || '5432'),
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
max: 20 // Connection pool size
});
}

schema: ToolSchema = {
input: {
type: 'object',
properties: {
queryType: {
type: 'string',
enum: ['getUser', 'getProducts', 'getOrders'],
description: 'Type of predefined query to execute'
},
parameters: {
type: 'object',
description: 'Query parameters'
}
},
required: ['queryType']
},
output: {
type: 'object',
properties: {
results: {
type: 'array',
items: {
type: 'object'
},
description: 'Query results'
},
count: {
type: 'number',
description: 'Number of results'
}
}
}
};

async execute(params: any): Promise<any> {
const { queryType, parameters = {} } = params;

// Define allowed queries
const queries = {
getUser: {
text: 'SELECT id, name, email FROM users WHERE id = $1',
values: [parameters.userId]
},
getProducts: {
text: 'SELECT id, name, price FROM products WHERE category = $1 LIMIT $2',
values: [parameters.category, parameters.limit || 10]
},
getOrders: {
text: 'SELECT id, customer_id, total FROM orders WHERE customer_id = $1',
values: [parameters.customerId]
}
};

if (!queries[queryType]) {
throw new Error(`Unknown query type: [queryType]`);
}

try {
const result = await this.pool.query(queries[queryType]);

return {
results: result.rows,
count: result.rowCount
};
} catch (error) {
throw new Error(`Database query error: [error.message]`);
}
}
}

File Operation Toolโ€‹

import { McpTool, ToolSchema } from '@llm-mcp/tool-sdk';
import * as fs from 'fs';
import * as path from 'path';

export class FileOperationTool implements McpTool {
name = 'file-operation-tool';
description = 'Perform file operations in a designated directory';
version = '1.0.0';

// Base directory for file operations (configurable via environment)
private baseDir: string;

constructor() {
this.baseDir = process.env.FILE_OPERATIONS_DIR || '/tmp/file-operations';

// Ensure base directory exists
if (!fs.existsSync(this.baseDir)) {
fs.mkdirSync(this.baseDir, { recursive: true });
}
}

schema: ToolSchema = {
input: {
type: 'object',
properties: {
operation: {
type: 'string',
enum: ['read', 'write', 'list', 'delete'],
description: 'File operation to perform'
},
filename: {
type: 'string',
description: 'Name of the file (relative to base directory)'
},
content: {
type: 'string',
description: 'Content to write (for write operation)'
}
},
required: ['operation']
},
output: {
type: 'object',
properties: {
success: {
type: 'boolean',
description: 'Operation success status'
},
data: {
type: 'string',
description: 'File content (for read operation) or operation result'
},
files: {
type: 'array',
items: {
type: 'string'
},
description: 'List of files (for list operation)'
}
}
}
};

validate(params: any): boolean {
const { operation, filename } = params;

// All operations except 'list' require a filename
if (operation !== 'list' && !filename) {
return false;
}

// Write operation requires content
if (operation === 'write' && !params.content) {
return false;
}

// Prevent path traversal attacks
if (filename && (
filename.includes('..') ||
filename.startsWith('/') ||
filename.includes('\\')
)) {
return false;
}

return true;
}

async execute(params: any): Promise<any> {
const { operation, filename, content } = params;

try {
switch (operation) {
case 'read': {
const filePath = path.join(this.baseDir, filename);
if (!fs.existsSync(filePath)) {
return { success: false, data: 'File not found' };
}
const data = fs.readFileSync(filePath, 'utf8');
return { success: true, data };
}

case 'write': {
const filePath = path.join(this.baseDir, filename);
fs.writeFileSync(filePath, content, 'utf8');
return { success: true, data: 'File written successfully' };
}

case 'list': {
const files = fs.readdirSync(this.baseDir);
return { success: true, files };
}

case 'delete': {
const filePath = path.join(this.baseDir, filename);
if (!fs.existsSync(filePath)) {
return { success: false, data: 'File not found' };
}
fs.unlinkSync(filePath);
return { success: true, data: 'File deleted successfully' };
}

default:
return { success: false, data: 'Invalid operation' };
}
} catch (error) {
return {
success: false,
data: `Error: [error.message]`
};
}
}
}

This comprehensive guide provides all the information needed to develop, test, and deploy custom tools for LLM-MCP. For additional help, consult the LLM-MCP API reference or contact the platform team.