summaryrefslogtreecommitdiff
path: root/mcp-servers/simple-mcp-server/.claude/commands/add-tool.md
diff options
context:
space:
mode:
authorTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-01-16 08:30:14 +0900
committerTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-01-16 08:30:14 +0900
commit3fbb9a18372f2b6a675dd6c039ba52be76f3eeb4 (patch)
treeaa694a36cdd323a7853672ee7a2ba60409ac3b06 /mcp-servers/simple-mcp-server/.claude/commands/add-tool.md
updates
Diffstat (limited to 'mcp-servers/simple-mcp-server/.claude/commands/add-tool.md')
-rw-r--r--mcp-servers/simple-mcp-server/.claude/commands/add-tool.md207
1 files changed, 207 insertions, 0 deletions
diff --git a/mcp-servers/simple-mcp-server/.claude/commands/add-tool.md b/mcp-servers/simple-mcp-server/.claude/commands/add-tool.md
new file mode 100644
index 0000000..da81212
--- /dev/null
+++ b/mcp-servers/simple-mcp-server/.claude/commands/add-tool.md
@@ -0,0 +1,207 @@
+# Add Tool to MCP Server
+
+Adds a new tool to your MCP server with proper schema validation and error handling.
+
+## Usage
+
+```
+/add-tool <name> <description> [parameters]
+```
+
+## Examples
+
+```
+/add-tool calculate "Performs mathematical calculations"
+/add-tool search "Search for information" query:string limit:number?
+/add-tool process_data "Process data with options" input:string format:enum[json,csv,xml]
+```
+
+## Implementation
+
+```typescript
+import { z } from 'zod';
+import * as fs from 'fs/promises';
+import * as path from 'path';
+
+async function addTool(name: string, description: string, parameters?: string[]) {
+ // Parse parameters into schema
+ const schema = parseParameterSchema(parameters || []);
+
+ // Generate tool file
+ const toolContent = generateToolFile(name, description, schema);
+
+ // Write tool file
+ const toolPath = path.join('src/tools', `${name}.ts`);
+ await fs.writeFile(toolPath, toolContent);
+
+ // Update tool index
+ await updateToolIndex(name);
+
+ // Generate test file
+ const testContent = generateToolTest(name);
+ const testPath = path.join('tests/unit/tools', `${name}.test.ts`);
+ await fs.writeFile(testPath, testContent);
+
+ console.log(`✅ Tool "${name}" added successfully!`);
+ console.log(` - Implementation: ${toolPath}`);
+ console.log(` - Test file: ${testPath}`);
+ console.log(`\nNext steps:`);
+ console.log(` 1. Implement the tool logic in ${toolPath}`);
+ console.log(` 2. Run tests with "npm test"`);
+ console.log(` 3. Test with MCP Inspector`);
+}
+
+function parseParameterSchema(parameters: string[]): any {
+ const properties: Record<string, any> = {};
+ const required: string[] = [];
+
+ for (const param of parameters) {
+ const [nameType, ...rest] = param.split(':');
+ const isOptional = nameType.endsWith('?');
+ const name = isOptional ? nameType.slice(0, -1) : nameType;
+ const type = rest.join(':') || 'string';
+
+ if (!isOptional) {
+ required.push(name);
+ }
+
+ properties[name] = parseType(type);
+ }
+
+ return {
+ type: 'object',
+ properties,
+ required: required.length > 0 ? required : undefined,
+ };
+}
+
+function parseType(type: string): any {
+ if (type.startsWith('enum[')) {
+ const values = type.slice(5, -1).split(',');
+ return {
+ type: 'string',
+ enum: values,
+ };
+ }
+
+ switch (type) {
+ case 'number':
+ return { type: 'number' };
+ case 'boolean':
+ return { type: 'boolean' };
+ case 'array':
+ return { type: 'array', items: { type: 'string' } };
+ default:
+ return { type: 'string' };
+ }
+}
+
+function generateToolFile(name: string, description: string, schema: any): string {
+ return `
+import { z } from 'zod';
+import type { ToolHandler } from '../types/tools.js';
+
+// Define Zod schema for validation
+const ${capitalize(name)}Schema = z.object({
+${generateZodSchema(schema.properties, ' ')}
+});
+
+export type ${capitalize(name)}Args = z.infer<typeof ${capitalize(name)}Schema>;
+
+export const ${name}Tool = {
+ name: '${name}',
+ description: '${description}',
+ inputSchema: ${JSON.stringify(schema, null, 2)},
+ handler: async (args: unknown): Promise<ToolHandler> => {
+ // Validate input
+ const validated = ${capitalize(name)}Schema.parse(args);
+
+ // TODO: Implement your tool logic here
+ const result = await process${capitalize(name)}(validated);
+
+ return {
+ content: [
+ {
+ type: 'text',
+ text: JSON.stringify(result),
+ },
+ ],
+ };
+ },
+};
+
+async function process${capitalize(name)}(args: ${capitalize(name)}Args) {
+ // TODO: Implement the actual processing logic
+ return {
+ success: true,
+ message: 'Tool executed successfully',
+ input: args,
+ };
+}
+`;
+}
+
+function generateZodSchema(properties: Record<string, any>, indent: string): string {
+ const lines: string[] = [];
+
+ for (const [key, value] of Object.entries(properties)) {
+ let zodType = 'z.string()';
+
+ if (value.type === 'number') {
+ zodType = 'z.number()';
+ } else if (value.type === 'boolean') {
+ zodType = 'z.boolean()';
+ } else if (value.enum) {
+ zodType = `z.enum([${value.enum.map((v: string) => `'${v}'`).join(', ')}])`;
+ } else if (value.type === 'array') {
+ zodType = 'z.array(z.string())';
+ }
+
+ lines.push(`${indent}${key}: ${zodType},`);
+ }
+
+ return lines.join('\n');
+}
+
+function capitalize(str: string): string {
+ return str.charAt(0).toUpperCase() + str.slice(1);
+}
+
+function generateToolTest(name: string): string {
+ return `
+import { describe, it, expect, vi } from 'vitest';
+import { ${name}Tool } from '../../src/tools/${name}.js';
+
+describe('${name} tool', () => {
+ it('should have correct metadata', () => {
+ expect(${name}Tool.name).toBe('${name}');
+ expect(${name}Tool.description).toBeDefined();
+ expect(${name}Tool.inputSchema).toBeDefined();
+ });
+
+ it('should validate input parameters', async () => {
+ const invalidInput = {};
+
+ await expect(${name}Tool.handler(invalidInput))
+ .rejects
+ .toThrow();
+ });
+
+ it('should handle valid input', async () => {
+ const validInput = {
+ // TODO: Add valid test input
+ };
+
+ const result = await ${name}Tool.handler(validInput);
+
+ expect(result).toHaveProperty('content');
+ expect(result.content[0]).toHaveProperty('type', 'text');
+ });
+
+ it('should handle errors gracefully', async () => {
+ // TODO: Add error handling tests
+ });
+});
+`;
+}
+``` \ No newline at end of file