Skip to content

feat: add native-only FME environment get, create, update, and delete - #833

Merged
puthrayaharness merged 5 commits into
harness:mainfrom
ravindraharness:fme-v4-remaining-environment
Aug 21, 2026
Merged

feat: add native-only FME environment get, create, update, and delete#833
puthrayaharness merged 5 commits into
harness:mainfrom
ravindraharness:fme-v4-remaining-environment

Conversation

@ravindraharness

@ravindraharness ravindraharness commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Description

Follow-up to #806 for remaining FME environment ops.

#806 dual-moded list only (workspace_id or org_id+project_id). MCP never had get/create/update/delete on workspace_id, so those four ops are Harness-native only. This PR does not invent a legacy Split v2 MCP contract (those Admin APIs exist; we are not exposing them).

Dual-mode routing — this PR only

Resource Legacy (workspace_id) Harness-native (org_id+project_id)
fme_environment list (unchanged dual-mode) list + get / create / update / delete

Native contracts

  • list — still dual-mode. Native list uses fmeV4PaginatedListExtract (dataitems, totalCounttotal) with offset/limit (harness_list size maps to limit).
  • getGET /fme/api/v4/environments/{environment_id} (UUID from list, not the env name).
  • createPOST /fme/api/v4/environments body { name, isProduction? } (CreateEnvironmentRequest). Name max 15 characters. production is accepted as an alias for isProduction. skipScopeBodyInjection so NG orgIdentifier/projectIdentifier are not injected.
  • updatePATCH JSON Merge Patch { name?, isProduction? }. Neither field is clearable (omit to keep).
  • deleteDELETE /fme/api/v4/environments/{id}. Backend returns 400 hasDependents while SDK API keys (always created by EnvironmentStarterKit), flags, or segments remain. MCP has no v4 token resource and does not auto-delete keys.

workspace_id on get/create/update/delete throws: Harness-native (org_id/project_id) only — MCP never supported workspace_id for this operation (list remains dual-mode).

Key implementation changes

  • src/registry/toolsets/feature-flags.ts plus tests/README.
  • src/registry/extractors.tsfmeV4PaginatedListExtract used by native environment list (same helper as traffic type / rollout status lists).
  • resolveNativeOnlyEnvironmentRoute for the four new ops. List still uses resolveFmeDualMode.
  • README Feature Flags matrix: fme_environment get/create/update/delete. Native list envelope/pagination documented without citing other PR numbers.
  • No registry/index.ts, types.ts, or prompt changes.

Type of Change

  • New feature

Checklist

  • Unit: tests/registry/fme-environment-native-only.test.ts + tests/registry/feature-flags.test.ts
  • pnpm docs:check (README matrix matches registry)

Coding Standards (registry-driven MCP model)

  • No new server.registerTool() calls — existing feature-flags toolset extended
  • operationPolicy on every new/changed endpoint
  • Shared response extractors from src/registry/extractors.ts
  • identifierFields and scope declared
  • No console.log() in src/

Test plan

  • Native create/get/update against qa.harness.io
  • workspace_id rejected on get/create/update/delete
  • Native delete: expected 400 hasDependents until starter-kit SDK keys are removed (no MCP token API)

List was already dual-mode after harness#806. Remaining CRUD follows v4 EnvironmentResource: isProduction on the wire, merge-patch update, UUID environment_id, and skipScopeBodyInjection on POST. Item get is native-only because Split v2 has no GET-by-id.

Co-authored-by: Cursor <cursoragent@cursor.com>
@CLAassistant

CLAassistant commented Aug 18, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 3 committers have signed the CLA.

✅ puthrayaharness
❌ cursoragent
❌ ravindraharness
You have signed the CLA already but the status is still pending? Let us recheck it.

Co-authored-by: Cursor <cursoragent@cursor.com>

harness#806 only dual-moded environment list. MCP never had a workspace_id contract for the other ops, so do not invent legacy v2 create/update/delete paths.
@ravindraharness ravindraharness changed the title feat: wire native FME environment get, create, update, and delete feat: add native-only FME environment get, create, update, and delete Aug 18, 2026
Java EnvironmentListResponse is paginated; passthrough dropped
totalCount. Product docs should not cite internal PR history.
Comment thread src/registry/toolsets/feature-flags.ts
Comment thread src/registry/toolsets/feature-flags.ts Outdated
const mode = resolveFmeDualMode(input, "fme_environment");
if (mode.mode === "legacy") {
throw new Error(
`fme_environment.${operation}: Harness-native (org_id/project_id) only — MCP never supported workspace_id for this operation (list remains dual-mode).`,

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.

MCP never supported workspace_id
We should talk about design in the description of the tools/resources.
We should explain the intent and that's it. Not go into details what the previous was prev supported or working.

Please revamp all the descriptions added/changed in this PR.

…scription

Co-authored-by: Rohan Gupta <thisrohangupta@users.noreply.github.com>
],
};

const fmeEnvironmentUpdateSchema: BodySchema = {

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.

Why do we have both isProduction and production? can we align on one for MCP? We should avoid adding such things for newer resources.

Comment thread src/registry/toolsets/feature-flags.ts
description:
"Feature Management environment. Supports list. Dual-mode scoping: pass either org_id+project_id " +
"(Harness-native, preferred — no workspace lookup needed) or the deprecated workspace_id.",
"Feature Management environment. Dual-mode list (workspace_id or org_id+project_id). get/create/update/delete are Harness-native only. Native create/update use isProduction (production accepted as an alias). Native PATCH is JSON Merge Patch; name and isProduction are not clearable. Name max 15 characters. Delete returns 400 hasDependents while SDK API keys (always created with a new env), flags, or segments remain.",

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.

Simplified the resource-level description to focus on scope and supported operations only. Removed API paths, merge-patch semantics, field constraints, and error-code details — those remain in the per-operation descriptions and body schemas where agents need them.

"Create an FME environment (Harness-native org_id+project_id only). name is required (max 15 characters). isProduction is optional (default false). production is accepted as an alias for isProduction.",
fields: [
{ name: "name", type: "string", required: true, description: "Environment name (unique in the project; max 15 characters)" },
{ name: "isProduction", type: "boolean", required: false, description: "Whether this is a production environment. Optional; defaults to false on the backend if omitted." },

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.

Agreed — aligned on isProduction only.

Removed the production alias from the create/update body schemas, the body builder helper, and the alias-mapping tests. MCP now exposes only isProduction, matching the Harness API field (CreateEnvironmentRequest.isProduction). README updated accordingly.

@harness harness deleted a comment from cursor Bot Aug 21, 2026
@puthrayaharness

Copy link
Copy Markdown
Contributor

@cursor can you review the PR?

@cursor

cursor Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

PR Review Summary

I've completed a comprehensive review of PR #833. The PR adds native-only FME environment operations (get, create, update, delete) as a follow-up to #806. Here's my assessment:

✅ Overall Status: APPROVED - Ready to Merge

Test Results

  • All tests pass: 3,028 tests including new native-only environment tests
  • Build successful: TypeScript compilation clean
  • Standards checks: 77 coding standards tests pass
  • Documentation: README in sync with implementation

Implementation Quality

Strengths:

  1. Correct architecture: Native-only operations properly reject workspace_id with clear error messages
  2. Dual-mode list preserved: List operation remains backward compatible
  3. Clean body handling: Only isProduction field used (no alias confusion)
  4. Proper scope injection: skipScopeBodyInjection: true correctly applied
  5. AGENTS.md compliance:
    • No console.log() usage
    • Correct Zod v4 imports (import * as z from "zod/v4")
    • operationPolicy set on all operations
    • Shared extractors used (fmeV4PaginatedListExtract, passthrough)

Test Coverage:

// Native get routes correctly
// workspace_id properly rejected on get/create/update/delete  
// Native create uses isProduction without NG body injection
// Native delete routes by environment_id

Code Implementation:

const fmeEnvironmentCreateSchema: BodySchema = {
  description:
    "Create an FME environment in a project. Requires org_id+project_id. name is required (max 15 characters). isProduction is optional (default false).",
  fields: [
    { name: "name", type: "string", required: true, description: "Environment name (unique in the project; max 15 characters)" },
    { name: "isProduction", type: "boolean", required: false, description: "Whether this is a production environment. Optional; defaults to false on the backend if omitted." },
  ],
};

Review Comments Addressed

All feedback from @puthrayaharness has been addressed:

  • ✅ Descriptions simplified (removed unnecessary MCP history details)
  • ✅ Only isProduction field exposed (no production alias)
  • ✅ Clear error messages focused on requirements

Documentation

README accurately documents the native-only pattern:

- **`fme_environment`** — `list` is dual-mode (`workspace_id` or `org_id`+`project_id`). `get`/`create`/`update`/`delete` require `org_id`+`project_id` and call `/fme/api/v4/environments`. List pagination: optional `offset`/`limit` (max 100; `harness_list` `size` maps to `limit`); response envelope `{data, limit, offset, totalCount}` is promoted to `items`/`total`. Create/update accept `isProduction`. Update is JSON Merge Patch; `name` and `isProduction` are not clearable. Name max 15 characters.

Recommendation

This PR is ready to merge. The implementation is clean, well-tested, follows all architectural patterns, and all review feedback has been addressed. The native-only constraint for get/create/update/delete operations is clearly documented and consistently enforced.

Open in Web Open in Cursor 

@puthrayaharness
puthrayaharness merged commit 5e604fc into harness:main Aug 21, 2026
8 checks passed
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.

4 participants