# Change who can use the tools and other filters

By the end of this page you can change who may use the tools, adjust the plugin’s limits, and record the tool calls that run on the server in your own code. This is a reference for developers.

Put the snippets in a small plugin or a file in `wp-content/mu-plugins/`, for example `wp-content/mu-plugins/btmcp-tweaks.php`.

## Who can use the tools

### `btmcp_capability`

The capability an account needs to use any tool. Default `manage_options`.

```
add_filter( 'btmcp_capability', function () {
	return 'edit_theme_options';
} );
```

Three things stay as they are when you lower it:

- The settings screen still needs `manage_options`.
- **Site administration** and **Read files** still need `manage_options`.
- Each group’s own requirement still applies. **Theme files** needs `edit_themes`, for example.

### `btmcp_connected_apps_show_all_users`

Whether **Connected apps** lists every user’s connections or only the viewer’s own. Default `true`.

```
add_filter(
	'btmcp_connected_apps_show_all_users',
	'__return_false'
);
```

## Abilities

### `btmcp_expose_ability`

Whether one Ability becomes a tool. It has the final say, in both directions. Receives the decision so far and the `WP_Ability` object.

```
function my_expose_ability( $exposed, $ability ) {
	if ( 'my-plugin/delete-all' === $ability->get_name() ) {
		return false;
	}
	return $exposed;
}
add_filter( 'btmcp_expose_ability', 'my_expose_ability', 10, 2 );
```

## Theme files

Each of these filters returns a number, except the last, which returns a list of names.

- `btmcp_batch_max_files`: files one change set may touch. Default `100`.
- `btmcp_batch_max_bytes`: total bytes of contents in one change set. Default `5242880`.
- `btmcp_write_limit`: bytes one written file may have. Default `2097152`.
- `btmcp_read_limit`: bytes one read may return. Default `1048576`.
- `btmcp_list_limit`: entries one listing may return. Default `5000`.
- `btmcp_change_set_keep`: change sets kept per theme. Default `50`.
- `btmcp_orphan_backup_days`: days a backup is kept after its file left the theme. Default `30`. `0` keeps it forever.
- `btmcp_backup_max_bytes`: size limit of one theme’s backup folder, in bytes. Default `0`, which means no limit.
- `btmcp_search_time_budget`: seconds one `btm.theme-search` call may take. Default `5`.
- `btmcp_search_excluded_dirs`: folder names the search never enters.

`btmcp_read_limit` and `btmcp_list_limit` also apply to the **Read files** group.

Allow one large file. A single file counts against the batch limit too, so raise both:

```
add_filter( 'btmcp_write_limit', function () {
	return 8 * MB_IN_BYTES;
} );
add_filter( 'btmcp_batch_max_bytes', function () {
	return 8 * MB_IN_BYTES;
} );
```

Keep more history:

```
add_filter( 'btmcp_change_set_keep', function () {
	return 200;
} );
```

Limit the backup folder to 50 MB per theme. The oldest backups go first, and a backup that a kept change set still needs is never removed:

```
add_filter( 'btmcp_backup_max_bytes', function () {
	return 50 * MB_IN_BYTES;
} );
```

Skip one more folder in `btm.theme-search`. The default list is `node_modules`, `vendor`, `vendor-dev` and `bower_components`:

```
add_filter( 'btmcp_search_excluded_dirs', function ( $names ) {
	$names[] = 'dist';
	return $names;
} );
```

## Content

### `btmcp_content_max_bytes`

The largest post content `btm.content-search` and `btm.content-replace` will look at. Default 1 MB. A larger post is skipped and counted.

```
add_filter( 'btmcp_content_max_bytes', function () {
	return 2 * MB_IN_BYTES;
} );
```

## Files

### `btmcp_filesystem_roots`

The folders the **Read files** tools are confined to. Default: `wp-content`. Return absolute paths. Entries that do not exist are dropped.

```
add_filter( 'btmcp_filesystem_roots', function () {
	return array( get_theme_root() );
} );
```

## OAuth and the endpoint

### `btmcp_oauth_client_ip`

The address the registration rate limit counts by. An address may register 10 applications an hour. The default is the address of the connection. Use the filter only when the site is behind a proxy that you trust to set the forwarding header, or every visitor counts as the proxy. For a site that only accepts traffic through Cloudflare:

```
add_filter( 'btmcp_oauth_client_ip', function ( $ip ) {
	$key = 'HTTP_CF_CONNECTING_IP';
	if ( empty( $_SERVER[ $key ] ) ) {
		return $ip;
	}
	$ip = wp_unslash( $_SERVER[ $key ] );
	return sanitize_text_field( $ip );
} );
```

### `btmcp_expose_error_detail`

Whether an internal error returned to a remote client includes the PHP error message. Default: the value of `WP_DEBUG`.

```
add_filter( 'btmcp_expose_error_detail', '__return_false' );
```

## The settings screen

### `btmcp_setup_client_connected`

Whether the **Get started** card counts its third step, **Connect a client**, as done. The default is true once an application has connected over OAuth, or once the activity log holds a call that came in over HTTP. A client that connects some other way, or a site that keeps the log switched off, can mark the step done:

```
add_filter( 'btmcp_setup_client_connected', '__return_true' );
```

### `btmcp_activity_keep`

How many entries the activity log keeps. Default `500`. `0` keeps none.

```
add_filter( 'btmcp_activity_keep', function () {
	return 2000;
} );
```

## Record tool calls

### `btmcp_tool_executed`

An action that fires each time a tool has run on the server. It does not fire for a call that was refused before it started, or for the tools that run only in the browser (`btm.request` and the browse tools).

- `$tool` (string): the tool name, for example `btm.theme-update-file`.
- `$context` (array): details of the call, such as a path or a size. It always has `transport`, which is `http` or `browser`. It never holds file contents or code.
- `$ok` (bool): whether the tool succeeded.
- `$user_id` (int): the account the call ran as.

```
function my_btmcp_log( $tool, $context, $ok, $user_id ) {
	error_log( sprintf(
		'[btmcp] %s by user %d over %s: %s',
		$tool,
		$user_id,
		$context['transport'],
		$ok ? 'ok' : 'failed'
	) );
}
add_action( 'btmcp_tool_executed', 'my_btmcp_log', 10, 4 );
```

## Filters that exist for tests

These let the plugin’s own test suite reach code paths a single test site cannot. Changing them on a live site makes the plugin’s checks describe a site that is not the real one. Leave them alone: `btmcp_abilities_api_available`, `btmcp_is_multisite`, `btmcp_is_block_theme`, `btmcp_environment_type`, `btmcp_request_auth_method`.

Source: https://w4dev.com/docs/block-theme-mcp/filters-and-actions/
