# Tool Discovery API

Discover available service functions and invoke them dynamically.

## Quick Start

```typescript
handler: async (input, ctx) => {
  // Discover all available tools
  const { services, summary } = await ctx.majk.toolDiscovery.discover_tools();
  ctx.logger.info(`Found ${summary.totalFunctions} functions`);

  // Get schema for a specific function
  const schema = await ctx.majk.toolDiscovery.get_tool_schema({
    functionName: 'list_reports'
  });

  // Invoke dynamically
  const result = await ctx.majk.toolDiscovery.invoke_tool({
    functionName: 'list_reports',
    parameters: { limit: 10 }
  });

  return { reports: result.reports };
}
```

## API Reference

### discover_tools(input?)

Discover available service functions.

```typescript
const { services, summary } = await ctx.majk.toolDiscovery.discover_tools({
  pluginId?: string,              // Filter by plugin
  category?: string,              // Filter by category
  functionNameContains?: string,  // Search function names
  builtinOnly?: boolean,          // Only built-in services
  requiresIdentity?: string       // Filter by identity requirement
});

// Returns:
{
  services: DiscoveredService[],
  summary: {
    totalServices: number,
    totalFunctions: number,
    byCategory: Record<string, number>,
    byPlugin: Record<string, number>
  }
}
```

### DiscoveredService

```typescript
interface DiscoveredService {
  pluginId: string;
  serviceName: string;
  displayName: string;
  description: string;
  isBuiltin: boolean;
  category?: string;
  functionCount: number;
  functions: DiscoveredFunction[];
}

interface DiscoveredFunction {
  name: string;
  description: string;
  inputSchema: Record<string, any>;
  identityRequirements?: Array<{
    identityType: string;
    required: boolean;
    description?: string;
  }>;
}
```

### get_tool_schema(input)

Get detailed schema for a function.

```typescript
const { function: fn, service } = await ctx.majk.toolDiscovery.get_tool_schema({
  functionName: string
});
// fn: DiscoveredFunction with full inputSchema
// service: { pluginId, serviceName, displayName, category? }
```

### list_tool_names()

Get simple list of all function names.

```typescript
const { functions, count } = await ctx.majk.toolDiscovery.list_tool_names();
// functions: string[]
```

### list_tool_categories()

List all tool categories.

```typescript
const { categories, count } = await ctx.majk.toolDiscovery.list_tool_categories();
// categories: string[]
```

### get_rpc_invocation_info(input)

Get RPC details for a function.

```typescript
const info = await ctx.majk.toolDiscovery.get_rpc_invocation_info({
  functionName: string
});
// Returns: { rpcServiceName, functionName, inputSchema, outputSchema?, readOnly, service, identityRequirements? }
```

### invoke_tool(input)

Invoke a function dynamically.

```typescript
const result = await ctx.majk.toolDiscovery.invoke_tool({
  functionName: string,
  parameters?: Record<string, any>,
  timeoutMs?: number
});
// Returns: Function result (type depends on function)
```

## Common Patterns

### Filter by Category

```typescript
// Find all delegation tools
const { services } = await ctx.majk.toolDiscovery.discover_tools({
  category: 'delegation'
});

for (const service of services) {
  console.log(`${service.displayName}: ${service.functionCount} functions`);
}
```

### Search Functions

```typescript
// Find functions related to reports
const { services } = await ctx.majk.toolDiscovery.discover_tools({
  functionNameContains: 'report'
});

const reportFunctions = services.flatMap(s => s.functions);
console.log('Report functions:', reportFunctions.map(f => f.name));
```

### Dynamic Invocation

```typescript
// Build a generic tool executor
async function executeTool(name: string, params: any) {
  // Validate function exists
  const { function: fn } = await ctx.majk.toolDiscovery.get_tool_schema({
    functionName: name
  });

  ctx.logger.info(`Invoking ${name}`, { params });

  const result = await ctx.majk.toolDiscovery.invoke_tool({
    functionName: name,
    parameters: params,
    timeoutMs: 30000
  });

  return result;
}
```

### Check Identity Requirements

```typescript
const { function: fn } = await ctx.majk.toolDiscovery.get_tool_schema({
  functionName: 'github_create_pr'
});

if (fn.identityRequirements?.some(r => r.required)) {
  const required = fn.identityRequirements.filter(r => r.required);
  ctx.logger.warn('Function requires identity:', required);
}
```

### Build Tool Browser

```typescript
// Get all tools organized by category
const { services, summary } = await ctx.majk.toolDiscovery.discover_tools();

const byCategory: Record<string, DiscoveredFunction[]> = {};

for (const service of services) {
  const category = service.category || 'uncategorized';
  byCategory[category] = byCategory[category] || [];
  byCategory[category].push(...service.functions);
}

// Display summary
for (const [category, functions] of Object.entries(byCategory)) {
  console.log(`\n${category} (${functions.length} functions)`);
  for (const fn of functions) {
    console.log(`  - ${fn.name}: ${fn.description}`);
  }
}
```

## Use Cases

1. **Plugin orchestration** - Discover and call functions from other plugins
2. **Dynamic workflows** - Build flexible automation based on available tools
3. **Tool documentation** - Generate docs from discovered schemas
4. **Validation** - Check function existence before invocation
5. **Admin interfaces** - Build tool browsers and executors

## Best Practices

1. **Cache discovery results** - Don't call discover_tools repeatedly
2. **Handle missing functions** - Check if function exists before invoke
3. **Validate parameters** - Use schema to validate inputs
4. **Set timeouts** - Use timeoutMs for long-running functions
5. **Check identity requirements** - Ensure required identities are available

## Next Steps

Run `npx @majkapp/plugin-kit --scripting` - Script execution API
Run `npx @majkapp/plugin-kit --services` - Service grouping patterns
Run `npx @majkapp/plugin-kit --rpc` - RPC and callbacks
