Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ Product teams own their definitions and control which operations are exposed as
list: true # marks as a list endpoint
enrich_url: '{id}' # appended to url_prefix for result URLs
category: Other product # overrides the file-level category, e.g. for $mcp_tool_category in MCP analytics
exclude_params: [field] # hide params from tool input
exclude_params: [field, steps.*.secret] # hide params and body fields from tool input (`*` steps into array items and dict values)
include_params: [field] # whitelist params (excludes all others)
response: # filter response fields (applied per-item on list endpoints)
include: [id, key, name] # keep only these fields (dot-path wildcards supported)
Expand Down Expand Up @@ -357,6 +357,7 @@ Product teams own their definitions and control which operations are exposed as
The MCP tool then requires the field, even when the generated PATCH body marks it optional.

Unknown keys are rejected at build time (Zod `.strict()`) to catch typos early.
An `exclude_params` entry that names no query parameter or request body field also fails the build, so a typo cannot leave the field exposed.

For list tools with a UI app, set `response.text_include` to the dot-path fields an agent
needs from each result row. This adds a compact text response for clients that cannot read
Expand Down
20 changes: 0 additions & 20 deletions products/autoresearch/mcp/tools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,6 @@ tools:
target_event, or from the action name when target_event is omitted, if you do not set it. It must be unique
among the project's non-archived pipelines. After creating, call autoresearch-train-create to start an
asynchronous agent training run.
exclude_params:
- id
- created_by
- created_at
- updated_at
- last_scored_at
- status
- iteration_budget_remaining
feature_flag: autoresearch
autoresearch-list:
operation: autoresearch_list
Expand Down Expand Up @@ -208,12 +200,6 @@ tools:
autoresearch-create with name set to suggested_name and the same five fields plus output_person_property.
For an action target, pass the same target_definition to both calls; target_event then only labels it, and
both calls need the action:read scope.
exclude_params:
- resolved_activity_event
- activity_event_alternatives
- display_name
- description
- notes
feature_flag: autoresearch
autoresearch-resume-create:
operation: autoresearch_resume_create
Expand Down Expand Up @@ -319,12 +305,6 @@ tools:
to see how the suggestion was interpreted. Examples: 'try a gradient boosting model', 'remove recency
features — I suspect leakage', 'the target event has a 7-day spike on Mondays, account for day-of-week'.
Suggestions survive pipeline pauses and are included in the next training batch when the pipeline resumes.
exclude_params:
- source
- status
- agent_response
- created_by
- linked_iteration_ids
feature_flag: autoresearch
autoresearch-suggestions-list:
operation: autoresearch_suggestions_list
Expand Down
17 changes: 1 addition & 16 deletions products/batch_exports/mcp/tools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,7 @@ tools:
convertToProjectTimezone, for example {"convertToProjectTimezone": true} to export them in the project
timezone.
exclude_params:
- id
- team_id
- created_at
- last_updated_at
- last_paused_at
- latest_runs
- filters
- start_at
- end_at
- integration
batch-export-delete:
operation: batch_exports_destroy
enabled: true
Expand Down Expand Up @@ -83,14 +74,8 @@ tools:
and Redshift. The destination type cannot be changed. Do not change the model field on an existing batch
export.
exclude_params:
- id
- team_id
- created_at
- last_updated_at
- last_paused_at
- latest_runs
- filters
- integration

batch-exports-list:
operation: batch_exports_list
enabled: true
Expand Down
3 changes: 0 additions & 3 deletions products/billing/mcp/tools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ tools:
period. For time-series breakdowns of usage call billing-usage-get; for cost (spend) breakdowns call
billing-spend-get. To check whether the customer has access to a specific feature (e.g. group analytics,
white-labelling), inspect `available_product_features` in the response.
exclude_params:
- limit
- offset
url_prefix: /organization/billing/overview
response:
exclude:
Expand Down
12 changes: 0 additions & 12 deletions products/dashboards/mcp/tools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -466,18 +466,6 @@ tools:
remove it. To add new widget tiles to this dashboard, use dashboard-widgets-batch-add instead. The returned
tiles omit insight results to save context — use dashboard-insights-run to fetch the actual data for each
insight.
exclude_params:
- creation_mode
- effective_restriction_level
- effective_privilege_level
- is_shared
- access_control_version
- last_refresh
- last_accessed_at
- deleted
- persisted_filters
- persisted_variables
- _create_in_folder
param_overrides:
id:
cast: string-int
Expand Down
1 change: 0 additions & 1 deletion products/persons/mcp/tools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,3 @@ tools:
'plan', 'role', or 'company'. Provide the property key and optionally a search value to filter results.
exclude_params:
- format
- force_refresh
6 changes: 0 additions & 6 deletions products/warehouse_sources/mcp/tools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ tools:
schemas (Stripe, Zendesk) but on a large production database (a Postgres/MySQL/BigQuery/Snowflake with many
tables) it syncs them all, which can be costly and noisy. When the user wants only specific tables, or
non-default sync types per table, use 'external-data-sources-create' instead.
exclude_params:
- client_secret
- account_id
param_overrides:
source_type:
input_schema: ExternalDataSourceTypeSchema
Expand Down Expand Up @@ -346,9 +343,6 @@ tools:
warehouse tables for revenue (Stripe), CRM (Hubspot, Salesforce), support (Zendesk), and your own databases
(Postgres, MySQL, BigQuery).
exclude_params:
- client_secret
- account_id
- job_inputs
- created_via
inject_body:
created_via: mcp
Expand Down
51 changes: 51 additions & 0 deletions services/mcp/scripts/generate-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ interface OpenApiSchema {
readOnly?: boolean
writeOnly?: boolean
items?: OpenApiSchema | { $ref: string }
additionalProperties?: OpenApiSchema | { $ref: string } | boolean
properties?: Record<string, OpenApiSchema>
required?: string[]
$ref?: string
Expand Down Expand Up @@ -502,6 +503,55 @@ interface SchemaComposition {
paramAliases: Record<string, string[]>
}

function assertExclusionsNameRealFields(
name: string,
config: ToolConfig,
resolved: ResolvedOperation,
spec: OpenApiSpec
): void {
const queryParamNames = new Set(
(resolved.operation.parameters ?? []).filter((p) => p.in === 'query').map((p) => p.name)
)
const bodySchema = resolved.operation.requestBody?.content?.['application/json']?.schema
for (const entry of config.exclude_params ?? []) {
if (!queryParamNames.has(entry) && !schemaHasPath(spec, bodySchema, entry.split('.'))) {
throw new Error(
`Enabled tool "${name}": exclude_params entry "${entry}" names no query parameter or body field, ` +
'so it hides nothing. Fix the name or remove the entry.'
)
}
}
}

function schemaHasPath(
spec: OpenApiSpec,
schemaOrRef: OpenApiSchema | { $ref: string } | undefined,
segments: string[]
): boolean {
const schema = schemaOrRef && resolveSchema(spec, schemaOrRef)
const [head, ...tail] = segments
if (!schema || head === undefined) {
return false
}
const variants = [...(schema.oneOf ?? []), ...(schema.anyOf ?? []), ...(schema.allOf ?? [])]
if (variants.some((variant) => schemaHasPath(spec, variant, segments))) {
return true
}
if (head === '*') {
return (
tail.length > 0 &&
[schema.items, schema.additionalProperties].some(
(child) => typeof child === 'object' && schemaHasPath(spec, child, tail)
)
)
}
const property =
schema.properties && Object.prototype.hasOwnProperty.call(schema.properties, head)
? schema.properties[head]
: undefined
return tail.length === 0 ? property !== undefined : schemaHasPath(spec, property, tail)
}

function composeToolSchema(
config: ToolConfig,
resolved: ResolvedOperation,
Expand Down Expand Up @@ -1833,6 +1883,7 @@ function generateCategoryFile(
process.exit(1)
}
try {
assertExclusionsNameRealFields(name, config, resolved, spec)
enabledTools.push([
name,
{
Expand Down
22 changes: 0 additions & 22 deletions services/mcp/src/generated/cdp_functions/api.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 0 additions & 22 deletions services/mcp/src/generated/error_tracking_alerts/api.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,9 @@
"inputs": {
"additionalProperties": {
"properties": {
"bytecode": {
"items": {},
"type": "array"
},
"bytecode_contract": {
"type": "string"
},
"order": {
"type": "number"
},
"templating": {
"description": "* `hog` - hog\n* `liquid` - liquid",
"enum": ["hog", "liquid"],
"type": "string"
},
"transpiled": {},
"value": {}
},
"type": "object"
Expand Down Expand Up @@ -285,22 +272,9 @@
"inputs": {
"additionalProperties": {
"properties": {
"bytecode": {
"items": {},
"type": "array"
},
"bytecode_contract": {
"type": "string"
},
"order": {
"type": "number"
},
"templating": {
"description": "* `hog` - hog\n* `liquid` - liquid",
"enum": ["hog", "liquid"],
"type": "string"
},
"transpiled": {},
"value": {}
},
"type": "object"
Expand Down
Loading