Skip to content

rust(feat): user defined function MCP tools - #739

Open
evan-sift wants to merge 7 commits into
rust/mcp-preview-rulefrom
rust/mcp-user-defined-functions
Open

rust(feat): user defined function MCP tools#739
evan-sift wants to merge 7 commits into
rust/mcp-preview-rulefrom
rust/mcp-user-defined-functions

Conversation

@evan-sift

@evan-sift evan-sift commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a user_defined_functions domain to the MCP server.

Tool surface: list_user_defined_functions, list_user_defined_function_versions, create_user_defined_function, update_user_defined_function, archive_user_defined_function, unarchive_user_defined_function.

Function inputs ride in function_inputs_json, a documented JSON string parameter. Updates are mask-only and create a new version; a name change applies alone per the API's semantics, so the tool rejects name combined with other fields.

Surface note: there is no dedicated archive RPC. The public API archives a user-defined function by setting the archive field through the update mask. archive_user_defined_function and unarchive_user_defined_function are exposed as separate tools anyway, so an agent does not have to know that, and so each can carry a destructive write gate.

The list tools carry the crate's fields projection and report count / has_more.

Stack note: the bundled agent skill and the 0.5.0 changelog for this whole stack land at the tip (#763).

Verification

  • cargo test -p sift_mcp on this branch: 411 passed, 0 failed (pagination, mask construction, no stale version echo, archive/unarchive shape, write gates, input validation, fields projection and count).
  • MCP protocol check against a development org: all six tools registered, live list round trip, all four write gates reject without their flags.
  • Agent tool-selection gates (list, versions, create-blocked, create, archive) pass against the full stack binary.

@evan-sift evan-sift changed the title rust/mcp user defined functions rust(feat): user defined function MCP tools Aug 19, 2026
@evan-sift
evan-sift force-pushed the rust/mcp-preview-rule branch from 505de4d to c49576a Compare August 26, 2026 07:56
@evan-sift
evan-sift force-pushed the rust/mcp-user-defined-functions branch from 269943c to 10cd137 Compare August 26, 2026 07:56
@evan-sift
evan-sift force-pushed the rust/mcp-preview-rule branch from c49576a to ac9064e Compare August 26, 2026 08:20
@evan-sift
evan-sift force-pushed the rust/mcp-user-defined-functions branch from 10cd137 to d23b02f Compare August 26, 2026 08:20
@evan-sift
evan-sift marked this pull request as ready for review August 26, 2026 08:21
@evan-sift
evan-sift requested a review from lineville August 26, 2026 08:21

@lineville lineville left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good mostly, I think the one issue to be fixed is with the user_notes being potentially overwritten with empty values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every update and every archive/unarchive will silently clear the user_notes on the new version. The go handler reads in user_notes and replaces it and we're passing it an empty value so I think we'll end up unintentionally wiping out those notes. I think we can solve this by passing through user_notes

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: update and archive/unarchive now pre-read the function and carry user_notes through, read-modify-write like the calculated-channel update. Tests assert the outgoing request carries the pre-read notes on both paths.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming rules here are less strict that the ones on the go backend which might cause some conflict, we might want to mirror what the backend has defined for name constraints.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: create and rename validate client-side with the backend rule (starts with a letter, then alphanumerics or underscore, max 253). One thing this surfaced: the backend's InvalidName message says names must end with a letter, but the regex allows trailing digits and underscores — message aligned in sift-stack/azimuth#13870.

@evan-sift
evan-sift force-pushed the rust/mcp-preview-rule branch from ac9064e to bda5135 Compare August 27, 2026 04:40
@evan-sift
evan-sift force-pushed the rust/mcp-user-defined-functions branch from 1d4b281 to 57dbeaf Compare August 27, 2026 04:40
@evan-sift
evan-sift requested a review from lineville August 27, 2026 04:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants