Skip to content

feat: explore_api result analysis in atp-compiler - #70

Merged
encodedz merged 1 commit into
masterfrom
feat/explore-result-filter-utils
Aug 10, 2026
Merged

feat: explore_api result analysis in atp-compiler#70
encodedz merged 1 commit into
masterfrom
feat/explore-result-filter-utils

Conversation

@encodedz

@encodedz encodedz commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the discovery-side counterpart to analyzeApiCalls: a client/gateway that proxies a remote ATP server it doesn't run itself (e.g. mcp-gateway talking to hosted ATP endpoints) needs to re-check an explore_api result against its own grant model before handing it to an agent. Today that means hand-rolling ATP's directory/function result shape and /apiGroup/... path convention client-side. This moves that parsing into atp-compiler, where analyzeApiCalls already lives for the mirror-image case (execute_code's request payload instead of explore_api's response payload).

New exports (@mondaydotcomorg/atp-compiler)

  • collectExploreOperations(result: ExploreResult): DetectedApiCall[] — every {apiGroup, operationId} leaf reachable in a directory listing or direct function result.
  • collectExploreOperationsFromValue(value: unknown): DetectedApiCall[] — same, over an already-JSON-parsed payload that may be a single result or an array (mirrors explore_api's paths: string | string[] input).
  • filterExploreResult(result, allowedOperations): ExploreResult | null — narrows a result to an allow-list. A denied function result returns null rather than a synthesized stand-in, mirroring ExplorerService.explore()'s own convention in atp-server — callers decide how "not visible" should look on the wire.
  • filterExploreResultValue(value, allowedOperations): unknown — same, over the array/single-result payload shape.

Notes

  • Reuses DetectedApiCall (already exported from analyzeApiCalls) rather than introducing a parallel type, since both are the same {apiGroup, operationId} identity.
  • Pure, no I/O — same contract as analyzeApiCalls. Callers own resolving the allow-list and deciding what a null becomes on the wire.
  • Directory listings are only ever narrowed at the level being explored; subdirectories are left alone and get filtered again on the caller's next explore_api call into them (no eager recursion/guessing).

Test plan

  • yarn jest in packages/atp-compiler — 351/351 passing (15 new)
  • yarn lint (tsc --noEmit) clean
  • yarn build clean
  • eslint 'packages/atp-compiler/src/**/*.ts' — zero new warnings/errors (all findings pre-existing, none in the new file)
  • prettier --check clean

🤖 Generated with Claude Code

Related: https://monday.monday.com/boards/4775886076/views/106679500/pulses/12733098176

…ations/filterExploreResult)

Discovery-side counterpart to analyzeApiCalls: a client/gateway proxying a
remote ATP server it doesn't run itself can now collect the {apiGroup,
operationId} leaves in an explore_api result and narrow that result to an
allow-list, without hand-rolling ATP's directory/function shape and
/apiGroup/... path convention itself.

- collectExploreOperations / collectExploreOperationsFromValue: derive
  DetectedApiCall[] from an ExploreResult (or an array of them, matching
  explore_api's paths input shape).
- filterExploreResult / filterExploreResultValue: narrow a result to an
  allow-list. A denied function result returns null (mirrors
  ExplorerService.explore()'s own convention) rather than a synthesized
  stand-in, leaving wire representation to the caller.
@encodedz
encodedz merged commit 13d498b into master Aug 10, 2026
3 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.

2 participants