llm-cli-gateway 2.6.3 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,52 @@ All notable changes to the llm-cli-gateway project.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## [2.7.0] - 2026-06-12: Provider capability inventory
8
+
9
+ ### Added
10
+
11
+ - Added `provider_tool_capabilities`, a read-only MCP tool that reports the
12
+ gateway request tools, provider kind, supported controls, feature flags,
13
+ model info, config-surface hints, local skill discovery, provider-native tool
14
+ discovery, unsupported/degraded inputs, warnings, and cache metadata for
15
+ Claude Code, Codex CLI, Gemini/Antigravity (`agy`), Grok CLI, optional
16
+ `grok_api`, and Mistral Vibe.
17
+ - Added `provider-tools://catalog` and per-provider resources
18
+ `provider-tools://claude`, `provider-tools://codex`,
19
+ `provider-tools://gemini`, `provider-tools://grok`,
20
+ `provider-tools://grok_api`, and `provider-tools://mistral` for clients that
21
+ prefer resource discovery over tool calls.
22
+ - Added `doctor --json` `provider_capabilities`, a compact setup-assistant
23
+ summary with schema version, resource URIs, per-provider request tools,
24
+ supported feature names, unsupported input names, config-surface counts,
25
+ discovered skill/tool counts, and warnings without raw local paths.
26
+ - Added bounded, redacted local skill/config discovery for provider capability
27
+ reporting. Grok local/bundled skills can now surface provider-native tools
28
+ such as Imagine `image_gen`, `image_edit`, `image_to_video`, and
29
+ `reference_to_video` when present, while keeping execution routed through
30
+ `grok_request`.
31
+
32
+ ### Changed
33
+
34
+ - Updated agent skills so LLM agents have provider-specific gateway usage
35
+ guidance for Claude, Codex, Gemini/Antigravity (`agy`), Grok, and Mistral
36
+ Vibe, and so orchestration skills check `provider_tool_capabilities` before
37
+ assuming tool allowlists, MCP-server semantics, sessions, output formats, or
38
+ provider-native tools.
39
+ - Updated setup assistant guidance and `setup/status.schema.json` so install
40
+ agents treat `doctor.provider_capabilities` as the compact source of truth
41
+ for outbound provider capability claims.
42
+ - Documented the intentionally published prod-only `npm-shrinkwrap.json` in
43
+ README and `socket.yml`, including the release audit and packed-consumer
44
+ checks that bound the shrinkwrap and shell-spawn Socket alerts.
45
+
46
+ ### Fixed
47
+
48
+ - Corrected stale internal skill guidance that described Codex continuity as
49
+ bookkeeping-only, described Gemini allowlists/MCP allowlists as pass-through,
50
+ omitted Mistral async from async orchestration docs, or encouraged copying
51
+ Claude tool names into other provider allowlists.
52
+
7
53
  ## [2.6.3] - 2026-06-12: Claude cache-control veracity and Grok 0.2.50
8
54
 
9
55
  ### Fixed
package/README.md CHANGED
@@ -62,6 +62,8 @@ The next documentation focus is provider-specific skill and DAG-TOML pairs for e
62
62
  - Security CI runs actionlint, zizmor, shellcheck, typos, osv-scanner, gitleaks, and lychee.
63
63
  - GitHub release installer artifacts are checksummed and signed with Sigstore keyless signing.
64
64
  - npm releases use provenance through OIDC trusted publishing.
65
+ - The npm package intentionally ships a generated, prod-only `npm-shrinkwrap.json` so registry installs resolve the audited release tree. Release gates regenerate it from `package-lock.json`, compare for parity, and run a registry-fidelity consumer install before publishing.
66
+ - Socket behavioural alerts are documented in [`socket.yml`](./socket.yml) and under "Security Considerations" below. `shellAccess` and `shrinkwrap` are reviewed package capabilities/configuration for this CLI appliance, not hidden install behaviour.
65
67
 
66
68
  ## Personal MCP Appliance
67
69
 
@@ -167,6 +169,7 @@ docker compose -f docker/personal.compose.yml run --rm doctor
167
169
  - **SQLite Flight Recorder**: Every request/response logged to `~/.llm-cli-gateway/logs.db` with correlation IDs, token usage, duration, retry counts, and circuit breaker state. Browse with [Datasette](https://datasette.io/): `datasette ~/.llm-cli-gateway/logs.db`
168
170
  - **Structured Metadata**: Tool responses include machine-readable `structuredContent` (model, cli, correlationId, sessionId, durationMs, token counts)
169
171
  - **Cache observability resources**: `cache-state://global`, `cache-state://session/{id}`, and `cache-state://prefix/{hash}` MCP resources return aggregate cache hit/miss/savings — tokens and hashes only, no prompt text. `session_get` includes a `cacheState` block when the session has prior requests.
172
+ - **Provider capability inventory**: `provider_tool_capabilities` and `provider-tools://catalog` expose the gateway request fields, supported/degraded provider controls, local skill/tool discovery, and safe config-surface hints for Claude Code, Codex CLI, Gemini/Antigravity, Grok CLI/API, and Mistral Vibe. `doctor --json` includes a compact `provider_capabilities` summary for setup assistants.
170
173
 
171
174
  ### Cache-aware operation
172
175
 
@@ -1019,6 +1022,42 @@ GEMINI_HISTORY_ROOT=/path/to/.gemini/tmp
1019
1022
  LLM_GATEWAY_DISABLE_MODEL_DISCOVERY=1
1020
1023
  ```
1021
1024
 
1025
+ ##### `provider_tool_capabilities`
1026
+
1027
+ Report the provider tool and feature capability catalog. Use this before
1028
+ orchestrating provider-specific requests so callers can distinguish supported
1029
+ controls, provider-owned configuration, ignored parity fields, and unsupported
1030
+ inputs.
1031
+
1032
+ **Parameters:**
1033
+
1034
+ - `cli` (string, optional): Provider filter (`"claude"`, `"codex"`, `"gemini"`, `"grok"`, `"grok_api"`, or `"mistral"`)
1035
+ - `includeSkills` (boolean, default `true`): Include bounded local skill discovery
1036
+ - `includeProviderTools` (boolean, default `true`): Include provider-native tools extracted from discovered skills
1037
+ - `includeUnsupported` (boolean, default `true`): Include explicit unsupported/degraded input records
1038
+ - `includePaths` (boolean, default `false`): Include raw local filesystem paths in discovery output
1039
+ - `refresh` (boolean, default `false`): Bypass the short-lived capability cache
1040
+
1041
+ The response schema is `provider-tool-capabilities.v2`. Capability discovery is
1042
+ read-only and bounded; raw local paths are redacted unless `includePaths` is
1043
+ explicitly true, and secret-bearing auth files are not read.
1044
+
1045
+ Equivalent MCP resources:
1046
+
1047
+ - `provider-tools://catalog`: full provider catalog
1048
+ - `provider-tools://claude`
1049
+ - `provider-tools://codex`
1050
+ - `provider-tools://gemini`
1051
+ - `provider-tools://grok`
1052
+ - `provider-tools://grok_api`
1053
+ - `provider-tools://mistral`
1054
+
1055
+ `doctor --json` also emits a compact `provider_capabilities` block with the
1056
+ same schema version, per-provider request tool names, supported feature names,
1057
+ unsupported input names, config-surface counts, discovery counts, and resource
1058
+ URIs. This block is intended for setup assistants that need a concise capability
1059
+ summary without local skill bodies or raw paths.
1060
+
1022
1061
  ##### `cli_versions`
1023
1062
 
1024
1063
  Report installed CLI versions.
@@ -1299,15 +1338,18 @@ The gateway supports concurrent requests across different CLIs. Each request spa
1299
1338
 
1300
1339
  ### Socket alerts — context for reviewers
1301
1340
 
1302
- If you're vetting `llm-cli-gateway` through [Socket](https://socket.dev/npm/package/llm-cli-gateway) or a similar supply-chain scanner, you'll see behavioural alerts and some dependency-ownership alerts. They are accurate descriptions of what the package does and what it depends on. The reviewed `shellAccess` capability is configured in `socket.yml` for repository/PR policy surfaces, but Socket's public package page may still display it for the published npm artifact; the rationale remains documented here and in the package.
1341
+ If you're vetting `llm-cli-gateway` through [Socket](https://socket.dev/npm/package/llm-cli-gateway) or a similar supply-chain scanner, you'll see behavioural alerts and some dependency-ownership alerts. They are accurate descriptions of what the package does and what it depends on. The reviewed `shellAccess` and `shrinkwrap` entries are configured in `socket.yml` for repository/PR policy surfaces, but Socket's public package page may still display them for the published npm artifact; the rationale remains documented here and in the package.
1342
+
1343
+ The currently flagged surfaces are not new in 2.6.x: the 2.3.0, 2.4.0, 2.5.0, and 2.6.3 npm tarballs all include `npm-shrinkwrap.json`, and all include the same `dist/executor.js` child-process spawn surface used to run provider CLIs. The `socket.yml` policy for 2.4.0, 2.5.0, 2.6.0, and 2.6.3 is materially the same for `shellAccess`; this README now adds the missing shrinkwrap disclosure as well.
1303
1344
 
1304
- | Alert | Where | Why it's bounded |
1305
- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1306
- | **Network access** | `src/http-transport.ts` opens an HTTP MCP transport when started via `npm run start:http`. `src/endpoint-exposure.ts` issues a HEAD probe to verify configured public/tunnel URLs. Socket also flagged `dist/upstream-contracts.js` in v1.17.2 from descriptive text, not a network call. | The transport binds to `127.0.0.1` by default and requires `LLM_GATEWAY_AUTH_TOKEN` to be set. The default stdio MCP entry point (`npm start`) opens no sockets. `src/upstream-contracts.ts` stores provider CLI metadata and imports no HTTP client APIs. |
1307
- | **Shell access** | `src/executor.ts` uses `child_process.spawn(cmd, args, …)` to invoke the underlying LLM CLIs. | `spawn` is called with an argument array and **never** `shell: true`, so there is no shell interpolation path for caller input. The command name is restricted to an allow-list of known CLI binaries (`claude`, `codex`, `agy`, `grok`, `vibe`). |
1308
- | **Uses eval** | None in our source. Transitive: `@modelcontextprotocol/sdk` `ajv@8` uses `new Function(...)` in `ajv/dist/compile/index.js` to compile JSON Schema validators. | This is ajv's standard codegen path. Only known schemas (defined in our source and the MCP SDK) flow into it; no caller-supplied data ever reaches the compiled function body. |
1309
- | **SQLite adapter isolation** | Persistence uses Node's built-in `node:sqlite` module (no native binding, no install scripts) through a single adapter, `src/sqlite-driver.ts`. | `node:sqlite` is touched by exactly one production module (the adapter); every other module talks to SQLite through its typed surface. We never call any `db.pragma()` helper (it does not exist on `node:sqlite`); SQLite setup uses fixed literal `db.exec("PRAGMA ...")` statements. `npm run security:audit` fails the release if production code references `node:sqlite` outside the adapter or reintroduces a `.pragma()` call. |
1310
- | **Dependency ownership** | A handful of small transitive packages (e.g. `media-typer` via `@modelcontextprotocol/sdk`) trip Socket's "unstable ownership" or "obfuscated code" heuristics. | These are pinned, well-known micro-deps in the Node ecosystem with no known issues. We pin direct override versions of `content-type` and `type-is` in `package.json#overrides`. As of 2.0.0 the prod graph carries no native module (`better-sqlite3` moved to devDependencies; `node:sqlite` is built into Node), eliminating the entire `prebuild-install`/`tar-fs`/`tar-stream` install-time chain. Our earlier direct dependency on `toml@3.0.0` was replaced with `smol-toml`. |
1345
+ | Alert | Where | Why it's bounded |
1346
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1347
+ | **Network access** | `src/http-transport.ts` opens an HTTP MCP transport when started via `npm run start:http`. `src/endpoint-exposure.ts` issues a HEAD probe to verify configured public/tunnel URLs. Socket also flagged `dist/upstream-contracts.js` in v1.17.2 from descriptive text, not a network call. | The transport binds to `127.0.0.1` by default and requires `LLM_GATEWAY_AUTH_TOKEN` to be set. The default stdio MCP entry point (`npm start`) opens no sockets. `src/upstream-contracts.ts` stores provider CLI metadata and imports no HTTP client APIs. |
1348
+ | **Shell access** | `src/executor.ts` uses `child_process.spawn(cmd, args, …)` to invoke the underlying LLM CLIs. | `spawn` is called with an argument array and **never** `shell: true`, so there is no shell interpolation path for caller input. The command name is restricted to an allow-list of known CLI binaries (`claude`, `codex`, `agy`, `grok`, `vibe`). |
1349
+ | **Published shrinkwrap** | The npm artifact includes `npm-shrinkwrap.json`; `package.json#files` includes it and `scripts/make-prod-shrinkwrap.mjs` generates it from `package-lock.json`. | This is a CLI/application package. npm documents the shrinkwrap use case for applications, daemons, and command-line tools published through the registry. Our shrinkwrap is a prod-only projection, not a committed full dev lockfile: `scripts/release-security-audit.sh` verifies parity with the audited lockfile, and `scripts/verify-registry-install.sh` proves fresh registry consumers receive no `better-sqlite3`/`prebuild-install`/`tar-fs`/`tar-stream` production chain. |
1350
+ | **Uses eval** | None in our source. Transitive: `@modelcontextprotocol/sdk` `ajv@8` uses `new Function(...)` in `ajv/dist/compile/index.js` to compile JSON Schema validators. | This is ajv's standard codegen path. Only known schemas (defined in our source and the MCP SDK) flow into it; no caller-supplied data ever reaches the compiled function body. |
1351
+ | **SQLite adapter isolation** | Persistence uses Node's built-in `node:sqlite` module (no native binding, no install scripts) through a single adapter, `src/sqlite-driver.ts`. | `node:sqlite` is touched by exactly one production module (the adapter); every other module talks to SQLite through its typed surface. We never call any `db.pragma()` helper (it does not exist on `node:sqlite`); SQLite setup uses fixed literal `db.exec("PRAGMA ...")` statements. `npm run security:audit` fails the release if production code references `node:sqlite` outside the adapter or reintroduces a `.pragma()` call. |
1352
+ | **Dependency ownership** | A handful of small transitive packages (e.g. `media-typer` via `@modelcontextprotocol/sdk`) trip Socket's "unstable ownership" or "obfuscated code" heuristics. | These are pinned, well-known micro-deps in the Node ecosystem with no known issues. We pin direct override versions of `content-type` and `type-is` in `package.json#overrides`. As of 2.0.0 the prod graph carries no native module (`better-sqlite3` moved to devDependencies; `node:sqlite` is built into Node), eliminating the entire `prebuild-install`/`tar-fs`/`tar-stream` install-time chain. Our earlier direct dependency on `toml@3.0.0` was replaced with `smol-toml`. |
1311
1353
 
1312
1354
  See [`socket.yml`](./socket.yml) for the same context in machine-readable form.
1313
1355
 
package/dist/doctor.d.ts CHANGED
@@ -2,6 +2,7 @@ import { type EndpointExposureReport } from "./endpoint-exposure.js";
2
2
  import { type ProviderLoginStatus } from "./provider-status.js";
3
3
  import type { FlightRecorderQuery } from "./flight-recorder.js";
4
4
  import { type CacheAwarenessConfig } from "./config.js";
5
+ import { type ProviderCapabilityId, type ProviderKind } from "./provider-tool-capabilities.js";
5
6
  export type CliType = "claude" | "codex" | "gemini" | "grok" | "mistral";
6
7
  export interface CacheAwarenessReport {
7
8
  enabled_features: Array<"anthropic_cache_control" | "ttl_warnings">;
@@ -17,6 +18,26 @@ export interface CacheAwarenessReport {
17
18
  total_cache_read_tokens: number;
18
19
  }>>;
19
20
  }
21
+ export interface ProviderCapabilitySummaryReport {
22
+ schema_version: "provider-tool-capabilities.v2";
23
+ tool: "provider_tool_capabilities";
24
+ resources: {
25
+ catalog: "provider-tools://catalog";
26
+ providers: Record<ProviderCapabilityId, string>;
27
+ };
28
+ cache_ttl_ms: number;
29
+ providers: Record<ProviderCapabilityId, {
30
+ provider_kind: ProviderKind;
31
+ cli_available: boolean;
32
+ gateway_request_tools: string[];
33
+ supported_features: string[];
34
+ unsupported_inputs: string[];
35
+ config_surface_count: number;
36
+ discovered_skill_count: number;
37
+ discovered_provider_tool_count: number;
38
+ warnings: string[];
39
+ }>;
40
+ }
20
41
  export interface VibeSessionLoggingStatus {
21
42
  config_path: string;
22
43
  config_present: boolean;
@@ -116,6 +137,7 @@ export interface DoctorReport {
116
137
  vibe_session_logging: VibeSessionLoggingStatus;
117
138
  };
118
139
  cache_awareness: CacheAwarenessReport;
140
+ provider_capabilities: ProviderCapabilitySummaryReport;
119
141
  upstream: {
120
142
  note: string;
121
143
  recommendation: string;
package/dist/doctor.js CHANGED
@@ -11,6 +11,7 @@ import { loadWorkspaceRegistry } from "./workspace-registry.js";
11
11
  import { computeGlobalCacheStats } from "./cache-stats.js";
12
12
  import { FlightRecorder, resolveFlightRecorderDbPath } from "./flight-recorder.js";
13
13
  import { buildUpstreamContractReport } from "./upstream-contracts.js";
14
+ import { getProviderToolCapabilities, providerCapabilityIds, } from "./provider-tool-capabilities.js";
14
15
  export function checkVibeSessionLogging(home = homedir()) {
15
16
  const configPath = join(home, ".vibe", "config.toml");
16
17
  if (!existsSync(configPath)) {
@@ -226,6 +227,49 @@ function buildCacheAwarenessReport(opts) {
226
227
  per_cli: perCli,
227
228
  };
228
229
  }
230
+ function buildProviderCapabilitySummary(providerStatuses) {
231
+ const capabilities = getProviderToolCapabilities({
232
+ includeSkills: true,
233
+ includeProviderTools: true,
234
+ includeUnsupported: true,
235
+ includePaths: false,
236
+ });
237
+ const providers = Object.fromEntries(providerCapabilityIds().map(provider => {
238
+ const capability = capabilities[provider];
239
+ if (!capability) {
240
+ throw new Error(`Missing provider capability record for ${provider}`);
241
+ }
242
+ const cliAvailable = provider === "grok_api"
243
+ ? capability.gatewayRequestTools.includes("grok_api_request")
244
+ : providerStatuses[provider].installed;
245
+ return [
246
+ provider,
247
+ {
248
+ provider_kind: capability.providerKind,
249
+ cli_available: cliAvailable,
250
+ gateway_request_tools: capability.gatewayRequestTools,
251
+ supported_features: Object.entries(capability.features)
252
+ .filter(([, feature]) => feature.supported)
253
+ .map(([name]) => name),
254
+ unsupported_inputs: capability.unsupportedInputs.map(input => input.input),
255
+ config_surface_count: capability.configSurfaces.length,
256
+ discovered_skill_count: capability.discoveredSkills.length,
257
+ discovered_provider_tool_count: capability.discoveredProviderTools.length,
258
+ warnings: capability.warnings,
259
+ },
260
+ ];
261
+ }));
262
+ return {
263
+ schema_version: "provider-tool-capabilities.v2",
264
+ tool: "provider_tool_capabilities",
265
+ resources: {
266
+ catalog: "provider-tools://catalog",
267
+ providers: Object.fromEntries(providerCapabilityIds().map(provider => [provider, `provider-tools://${provider}`])),
268
+ },
269
+ cache_ttl_ms: 60_000,
270
+ providers,
271
+ };
272
+ }
229
273
  export function createDoctorReport(envOrOptions = process.env) {
230
274
  const opts = isCreateDoctorReportOptions(envOrOptions)
231
275
  ? envOrOptions
@@ -316,6 +360,7 @@ export function createDoctorReport(envOrOptions = process.env) {
316
360
  endpoint_exposure: endpointExposure,
317
361
  client_config: clientConfigStatus(),
318
362
  cache_awareness: buildCacheAwarenessReport(opts),
363
+ provider_capabilities: buildProviderCapabilitySummary(providerStatuses),
319
364
  upstream,
320
365
  next_actions: [],
321
366
  };
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ import { loadConfig, loadPersistenceConfig, loadCacheAwarenessConfig, loadProvid
22
22
  import { createXaiResponse, XaiApiError, } from "./xai-api-provider.js";
23
23
  import { checkHealth } from "./health.js";
24
24
  import { clearModelRegistryCache, getAvailableCliInfo, getCliInfo, resolveModelAlias, } from "./model-registry.js";
25
+ import { getProviderToolCapabilities } from "./provider-tool-capabilities.js";
25
26
  import { AsyncJobManager, } from "./async-job-manager.js";
26
27
  import { createJobStore } from "./job-store.js";
27
28
  import { ApprovalManager } from "./approval-manager.js";
@@ -1049,6 +1050,27 @@ function registerBaseResources(server, runtime) {
1049
1050
  const contents = await runtime.resourceProvider.readResource(uri.href);
1050
1051
  return { contents: contents ? [contents] : [] };
1051
1052
  });
1053
+ server.registerResource("provider-tools-catalog", "provider-tools://catalog", {
1054
+ title: "Provider Tool Capabilities Catalog",
1055
+ description: "Read-only catalog of gateway tool controls and discovered provider skills",
1056
+ mimeType: "application/json",
1057
+ }, async (uri) => {
1058
+ runtime.logger.debug("Reading provider-tools://catalog resource");
1059
+ const contents = await runtime.resourceProvider.readResource(uri.href);
1060
+ return { contents: contents ? [contents] : [] };
1061
+ });
1062
+ server.registerResource("provider-tools", new ResourceTemplate("provider-tools://{provider}", { list: undefined }), {
1063
+ title: "Provider Tool Capabilities",
1064
+ description: "Read-only gateway tool controls and discovered local skills for one provider CLI",
1065
+ mimeType: "application/json",
1066
+ }, async (uri, variables) => {
1067
+ const provider = Array.isArray(variables.provider)
1068
+ ? variables.provider[0]
1069
+ : variables.provider;
1070
+ runtime.logger.debug(`Reading provider-tools://${provider}`);
1071
+ const contents = await runtime.resourceProvider.readResource(uri.href);
1072
+ return { contents: contents ? [contents] : [] };
1073
+ });
1052
1074
  }
1053
1075
  function resolvePromptOrPartsForPrep(args) {
1054
1076
  const hasPrompt = typeof args.prompt === "string" && args.prompt.length > 0;
@@ -5415,6 +5437,44 @@ export function createGatewayServer(deps = {}) {
5415
5437
  const result = cli ? { [cli]: cliInfo[cli] } : cliInfo;
5416
5438
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
5417
5439
  });
5440
+ server.tool("provider_tool_capabilities", "Report provider tool/feature capabilities and discovered local skill/tool integrations for claude|codex|gemini|grok|grok_api|mistral.", {
5441
+ cli: z
5442
+ .preprocess(value => (value === "" || value === null ? undefined : value), z.enum(["claude", "codex", "gemini", "grok", "grok_api", "mistral"]).optional())
5443
+ .describe("Provider filter (claude|codex|gemini|grok|grok_api|mistral)"),
5444
+ includeSkills: z
5445
+ .boolean()
5446
+ .default(true)
5447
+ .describe("Include bounded local skill discovery results"),
5448
+ includeProviderTools: z
5449
+ .boolean()
5450
+ .default(true)
5451
+ .describe("Include provider-native tools extracted from local skills"),
5452
+ includeUnsupported: z
5453
+ .boolean()
5454
+ .default(true)
5455
+ .describe("Include explicit unsupported/degraded input records"),
5456
+ includePaths: z
5457
+ .boolean()
5458
+ .default(false)
5459
+ .describe("Include raw local filesystem paths in discovery output"),
5460
+ refresh: z.boolean().default(false).describe("Bypass the short-lived capability cache"),
5461
+ }, {
5462
+ title: "Provider tool capabilities",
5463
+ readOnlyHint: true,
5464
+ destructiveHint: false,
5465
+ idempotentHint: true,
5466
+ openWorldHint: false,
5467
+ }, async ({ cli, includeSkills, includeProviderTools, includeUnsupported, includePaths, refresh, }) => {
5468
+ const capabilities = getProviderToolCapabilities({
5469
+ cli,
5470
+ includeSkills,
5471
+ includeProviderTools,
5472
+ includeUnsupported,
5473
+ includePaths,
5474
+ refresh,
5475
+ });
5476
+ return { content: [{ type: "text", text: JSON.stringify(capabilities, null, 2) }] };
5477
+ });
5418
5478
  server.tool("cli_versions", "Report installed provider CLI versions, availability, and login status for all five providers or one.", {
5419
5479
  cli: z
5420
5480
  .preprocess(value => (value === "" || value === null ? undefined : value), z.enum(["claude", "codex", "gemini", "grok", "mistral"]).optional())
@@ -0,0 +1,97 @@
1
+ import { type CliInfo } from "./model-registry.js";
2
+ import { type CliType } from "./session-manager.js";
3
+ export interface ProviderToolControl {
4
+ name?: string;
5
+ supported: boolean;
6
+ requestField?: string;
7
+ cliFlag?: string;
8
+ behavior: string;
9
+ }
10
+ export type ProviderCapabilityId = CliType | "grok_api";
11
+ export type ProviderKind = "cli" | "api";
12
+ export type UnsupportedInputBehavior = "reject" | "ignored" | "not_supported" | "approval_tracking_only" | "deprecated";
13
+ export type ProviderToolConfidence = "high" | "medium" | "low";
14
+ export type ProviderToolExtractionReason = "exact-tool-section" | "known-tool-name" | "backtick-heuristic" | "low-confidence";
15
+ export interface ProviderSkillCapability {
16
+ name: string;
17
+ source: "user" | "bundled";
18
+ path?: string;
19
+ description?: string;
20
+ declaredTools: string[];
21
+ declaredToolReasons?: Partial<Record<string, ProviderToolExtractionReason>>;
22
+ }
23
+ export interface ProviderNativeToolCapability {
24
+ name: string;
25
+ source: string;
26
+ skillName?: string;
27
+ path?: string;
28
+ confidence: ProviderToolConfidence;
29
+ reason: ProviderToolExtractionReason;
30
+ }
31
+ export interface ProviderConfigSurface {
32
+ name: string;
33
+ kind: "file" | "directory" | "env" | "gateway" | "provider";
34
+ present: boolean;
35
+ path?: string;
36
+ entries?: string[];
37
+ details?: string;
38
+ }
39
+ export interface ProviderUnsupportedInput {
40
+ input: string;
41
+ behavior: UnsupportedInputBehavior;
42
+ details: string;
43
+ }
44
+ export interface ProviderFeatureCapability {
45
+ supported: boolean;
46
+ details?: string;
47
+ values?: string[];
48
+ }
49
+ export type ProviderFeatureMap = Record<string, ProviderFeatureCapability>;
50
+ export interface ProviderCapabilityControls {
51
+ allowlist: ProviderToolControl;
52
+ denylist: ProviderToolControl;
53
+ mcpServers: ProviderToolControl;
54
+ nativeSkills: ProviderToolControl;
55
+ [name: string]: ProviderToolControl;
56
+ }
57
+ export interface ProviderToolCapabilities {
58
+ schemaVersion: "provider-tool-capabilities.v2";
59
+ generatedAt: string;
60
+ cli: ProviderCapabilityId;
61
+ providerKind: ProviderKind;
62
+ gatewayRequestTools: string[];
63
+ modelInfo: CliInfo | GrokApiModelInfo;
64
+ summary: string;
65
+ controls: ProviderCapabilityControls;
66
+ features: ProviderFeatureMap;
67
+ discoveredSkills: ProviderSkillCapability[];
68
+ discoveredProviderTools: ProviderNativeToolCapability[];
69
+ configSurfaces: ProviderConfigSurface[];
70
+ unsupportedInputs: ProviderUnsupportedInput[];
71
+ warnings: string[];
72
+ metadata: {
73
+ deprecatedFields?: Record<string, string>;
74
+ cacheTtlMs: number;
75
+ };
76
+ gatewayRequestTool: string;
77
+ }
78
+ export interface GrokApiModelInfo {
79
+ description: string;
80
+ models: Record<string, string>;
81
+ defaultModel?: string;
82
+ defaultModelSource?: string;
83
+ warnings?: string[];
84
+ }
85
+ export interface ProviderCapabilityQuery {
86
+ cli?: ProviderCapabilityId;
87
+ includeSkills?: boolean;
88
+ includeProviderTools?: boolean;
89
+ includeUnsupported?: boolean;
90
+ includePaths?: boolean;
91
+ refresh?: boolean;
92
+ }
93
+ export type ProviderToolCapabilitiesMap = Partial<Record<ProviderCapabilityId, ProviderToolCapabilities>>;
94
+ export declare function getProviderToolCapabilities(queryOrCli?: ProviderCapabilityQuery | ProviderCapabilityId): ProviderToolCapabilitiesMap;
95
+ export declare function getOneProviderToolCapabilities(cli: ProviderCapabilityId, queryOrCli?: ProviderCapabilityQuery | ProviderCapabilityId): ProviderToolCapabilities;
96
+ export declare function clearProviderToolCapabilitiesCache(): void;
97
+ export declare function providerCapabilityIds(): readonly ProviderCapabilityId[];