You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Addresses feedback from agent sessions using the architect and bundle-dev plugins, where get_deployment_logs output overflowed tool-result limits, deployment params had to be echoed back verbatim for every action, and API limits surfaced only as runtime errors.
get_deployment_logs: bounded output and easier follow/resume
Output now defaults to the most recent 40KB (a single Azure App Service deploy previously returned 62.8KB / 1,125 lines, overflowing MCP tool-result limits). A leading note reports when older content was elided, so truncation is never silent.
New tail_lines param: pass N for exactly the last N lines, -1 for the complete log, or omit for the default 40KB cap.
Log content is never rewritten — the returned text (after the note line) is always a verbatim suffix of the real log, including ANSI color codes.
Follow-mode timeouts now report the current status and explicitly instruct the agent to call again with follow=true to keep waiting. Since tail_lines composes with follow, repeat calls can use a small tail to avoid re-reading output (the SDK re-emits the full backfill on each follow; the cap bounds it).
New use_latest_params flag reuses the instance's saved params (from its most recent deployment) instead of requiring the agent to read get_instance.params and echo it back — the common loop for DECOMMISSION, PLAN of current config, and redeploy-as-is.
Mutually exclusive with params; fails with a clear error if the instance has never been deployed.
Input schema constraints for API limits that previously surfaced only at runtime
maxLength: 255 on description for project, environment, and component create/clone/fork/update tools (a 255-char overrun previously cost agents two blind retries), enforced by the go-sdk before the call reaches the API.
maxLength: 20 on creation-time identifier slugs (create_project, clone_project, create_environment, fork_environment, add_component). Lookup id fields on get/update tools are unconstrained since full identifiers like myproj-staging exceed the slug limit.
Fixed stale "max 12 characters" prose on project identifiers (the live API allows 20).
metadata.go constraint helpers refactored so enum and maxLength constraints compose on a shared inferred schema.
create_custom_attribute: documented key rules
Tool and key field descriptions now document that keys are unique org-wide across ALL scopes (case-insensitive) and the key format (1-64 chars, identifier-like, md- reserved), so agents pick per-scope key names up front instead of discovering the collision via the API's misleading organizationId: has already been taken error. (The error message itself will be fixed API-side.)
Test plan
Unit tests for tailLogs covering the default byte cap, verbatim-suffix property, single-line-exceeding-cap fallback, rune-boundary truncation, explicit tail_lines, and -1 passthrough.
Handler tests for snapshot tailing, follow-mode status header, use_latest_params (reuse, mutual exclusion, never-deployed), and maxLength presence on all constrained schema properties.
go build, go vet, gofmt, and the full go test ./... suite pass.
Double-check Instance.Params semantics for use_latest_params edge case
Post final review feedback
Solid, well-scoped PR — good test coverage on the new behaviors and the descriptions/error messages are unusually careful about agent ergonomics. A few notes:
Minor: use_latest_params can't distinguish "never deployed" from "deployed with an empty params schema"
latestInstanceParams (mcp/tools/deployments.go:490-502) uses len(instance.Params) == 0 to detect "never deployed":
iflen(instance.Params) ==0 {
returnnil, fmt.Errorf("%s: use_latest_params requires an instance that has been deployed before, but instance %s has no saved params — pass params explicitly", toolName, instanceID)
}
get_instance's own docs already note params are "empty until first deployed" — same ambiguity. But an instance whose bundle has an empty/trivial paramsSchema (no configurable params) would, after a real, successful deployment, legitimately have Params unmarshal to a non-nil empty map ({}), which len() can't distinguish from nil/never-deployed. For such an instance, use_latest_params: true would incorrectly fail with "has no saved params" / "requires an instance that has been deployed before" even though it has been deployed — it just has nothing to save.
This is a narrow edge case (bundles with zero configurable params aren't the common case) and pre-existing ambiguity in the underlying data, not a regression this PR introduces wholesale — but since this PR turns that ambiguous signal into a hard error (previously it was just descriptive text), it's worth a decision: either accept the edge case as acceptably rare, or special-case it if the SDK instance type exposes anything to distinguish "has a deployment" from "has saved params" (e.g. a deployment count/history field, or a schema check against paramsSchema.properties being empty). Not a blocker either way.
Everything else looks correct
tailLogs (mcp/tools/logs.go): the byte-cap/line-cap/-1 logic is correct, the verbatim-suffix guarantee holds, and the rune-boundary handling for the single-oversized-line case is a nice touch. Tests cover the interesting edge cases well (multibyte truncation, oversized single line, no-op when under cap).
Follow-mode timeout messaging (mcp/tools/deployments.go:154-165): clear instruction to retry with follow=true, and tail_lines composes correctly with both snapshot and follow paths.
use_latest_params mutual exclusion (mcp/tools/deployments.go:492-494): correctly checked before the API call, so passing params: {} (non-nil empty map) alongside the flag is correctly rejected rather than silently ignored.
metadata.go schema helpers: toolSchema/mustProp refactor cleanly lets applyEnums and applyMaxLengths compose on the same tool's schema regardless of init order. applyMaxLengths correctly limits constraints to creation-time slugs while leaving lookup id fields (e.g. myproj-staging) unconstrained.
create_custom_attribute docs: the org-wide/case-insensitive key collision behavior and md- reserved prefix are now documented up front, matching the stated goal of avoiding a blind API round-trip.
go.sum: just dedup of stale massdriver-sdk-go versions from a prior go mod tidy, consistent with pinning to v0.2.17.
Note on verification
I was not able to run go build/go vet/go test in this sandbox (tool execution required approval that wasn't available here), so I verified correctness by reading the diff and tests rather than executing them. The PR description states the full suite passes; you may want to confirm CI is green before merging.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Addresses feedback from agent sessions using the architect and bundle-dev plugins, where
get_deployment_logsoutput overflowed tool-result limits, deployment params had to be echoed back verbatim for every action, and API limits surfaced only as runtime errors.get_deployment_logs: bounded output and easier follow/resumetail_linesparam: passNfor exactly the last N lines,-1for the complete log, or omit for the default 40KB cap.follow=trueto keep waiting. Sincetail_linescomposes withfollow, repeat calls can use a small tail to avoid re-reading output (the SDK re-emits the full backfill on each follow; the cap bounds it).create_deployment/propose_deployment:use_latest_paramsuse_latest_paramsflag reuses the instance's saved params (from its most recent deployment) instead of requiring the agent to readget_instance.paramsand echo it back — the common loop for DECOMMISSION, PLAN of current config, and redeploy-as-is.params; fails with a clear error if the instance has never been deployed.Input schema constraints for API limits that previously surfaced only at runtime
maxLength: 255ondescriptionfor project, environment, and component create/clone/fork/update tools (a 255-char overrun previously cost agents two blind retries), enforced by the go-sdk before the call reaches the API.maxLength: 20on creation-time identifier slugs (create_project,clone_project,create_environment,fork_environment,add_component). Lookupidfields on get/update tools are unconstrained since full identifiers likemyproj-stagingexceed the slug limit.metadata.goconstraint helpers refactored so enum and maxLength constraints compose on a shared inferred schema.create_custom_attribute: documented key ruleskeyfield descriptions now document that keys are unique org-wide across ALL scopes (case-insensitive) and the key format (1-64 chars, identifier-like,md-reserved), so agents pick per-scope key names up front instead of discovering the collision via the API's misleadingorganizationId: has already been takenerror. (The error message itself will be fixed API-side.)Test plan
tailLogscovering the default byte cap, verbatim-suffix property, single-line-exceeding-cap fallback, rune-boundary truncation, explicittail_lines, and-1passthrough.use_latest_params(reuse, mutual exclusion, never-deployed), and maxLength presence on all constrained schema properties.go build,go vet,gofmt, and the fullgo test ./...suite pass.🤖 Generated with Claude Code