> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/wevm/incur/llms.txt
> Use this file to discover all available pages before exploring further.

# Mcp

> Expose CLI commands as MCP (Model Context Protocol) tools

The `Mcp` module starts a stdio MCP server that exposes CLI commands as tools, enabling AI agents to discover and call your commands through the Model Context Protocol.

## Functions

### serve

Starts a stdio MCP server that exposes commands as tools.

```typescript theme={null}
async function serve(
  name: string,
  version: string,
  commands: Map<string, any>,
  options?: serve.Options
): Promise<void>
```

<ParamField path="name" type="string" required>
  The MCP server name
</ParamField>

<ParamField path="version" type="string" required>
  Server version
</ParamField>

<ParamField path="commands" type="Map<string, any>" required>
  Map of commands to expose as tools
</ParamField>

<ParamField path="options" type="serve.Options">
  Server configuration options
</ParamField>

<ResponseField name="return" type="Promise<void>">
  Promise that resolves when the server connects and starts
</ResponseField>

#### Example

```typescript theme={null}
import { Cli, Mcp } from 'incur'

const cli = Cli.create({
  name: 'mycli',
  version: '1.0.0',
  commands: {
    greet: Cli.command({
      args: z.object({ name: z.string() }),
      run: ({ args }) => `Hello, ${args.name}!`
    })
  }
})

// Start MCP server
if (process.argv.includes('--mcp')) {
  await Mcp.serve(cli.name, cli.version, cli.commands)
} else {
  await cli.run()
}
```

## Types

### serve.Options

Options for the MCP server.

```typescript theme={null}
type Options = {
  /** Override input stream. Defaults to `process.stdin` */
  input?: Readable | undefined
  /** Override output stream. Defaults to `process.stdout` */
  output?: Writable | undefined
}
```

<ResponseField name="input" type="Readable">
  Override input stream. Defaults to `process.stdin`.
</ResponseField>

<ResponseField name="output" type="Writable">
  Override output stream. Defaults to `process.stdout`.
</ResponseField>

## How It Works

The MCP server:

1. **Flattens command hierarchy** - Nested commands become flat tools with underscore-separated names (e.g., `db_migrate`)
2. **Merges schemas** - Combines `args` and `options` into a single `inputSchema` for each tool
3. **Handles streaming** - Supports async generator commands with progress notifications
4. **Error handling** - Returns structured errors using `context.error()` or catches exceptions

### Tool Naming

Commands are converted to tool names by joining the command path with underscores:

```typescript theme={null}
// Command: mycli db migrate
// Tool name: db_migrate

// Command: mycli server start
// Tool name: server_start
```

### Input Schema

The tool's `inputSchema` merges both positional arguments and options into a flat object:

```typescript theme={null}
Cli.command({
  args: z.object({ id: z.number() }),
  options: z.object({ verbose: z.boolean().optional() }),
  run: ({ args, options }) => { /* ... */ }
})

// MCP tool receives:
// { id: 42, verbose: true }
```

### Streaming Commands

Async generator commands send progress notifications:

```typescript theme={null}
Cli.command({
  run: async function* ({ args }) {
    yield { status: 'starting' }
    await doWork()
    yield { status: 'complete' }
  }
})

// MCP client receives progress notifications
// Final result is an array of all yielded values
```

## Related

* [SyncMcp](/api/mcp) - Register CLI as MCP server with AI agents
* [Model Context Protocol](https://modelcontextprotocol.io) - Official MCP documentation
