Skip to content

feat(mcp): application read tools - #7716

Merged
cstns merged 8 commits into
feat/extend-mcp-tool-feature-setfrom
feat/mcp-tools-application-read
Aug 26, 2026
Merged

feat(mcp): application read tools#7716
cstns merged 8 commits into
feat/extend-mcp-tool-feature-setfrom
feat/mcp-tools-application-read

Conversation

@andypalmi

@andypalmi andypalmi commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 1 read-only MCP tools for the application resource, added to forge/ee/lib/mcp/tools/applications.js:

  • platform_list_application_snapshots - GET /applications/:applicationId/snapshots
  • platform_list_team_instance_statuses - GET /teams/:teamId/applications/status

This PR also extends the already-shipped platform_get_application_audit_log tool with an includeChildren argument.

Each tool describes the application resource, so all are filed with the existing application tools, following the one-file-per-resource convention. platform_list_team_instance_statuses returns the applications in a team with the live status of their instances and devices.

All tools are annotated readOnlyHint: true, destructiveHint: false.

Permissions:
#8185 removed the hardcoded user:expert-mcp scope allow-list, so expert MCP tokens now inherit the user's permissions gated by team role and no allow-list entries are needed.

Closes #7690

Consolidation notes

  • The three per-application instance listers (platform_get_application_hosted_instances, platform_get_application_remote_instances, platform_get_application_instances_status) are not added, because the unified platform_list_hosted_instances and platform_list_remote_instances tools already cover per-application listing via their applicationId argument, and live status via includeLiveStatus on platform_list_hosted_instances.
  • platform_get_application_audit_log gains an includeChildren argument to pull in descendant entries within the chosen scope.

Test plan

  • eslint on changed files passes with no errors
  • mocha unit tests pass

@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.04%. Comparing base (d3419bb) to head (8bf989e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7716      +/-   ##
==========================================
+ Coverage   75.94%   76.04%   +0.09%     
==========================================
  Files         445      445              
  Lines       23990    23988       -2     
  Branches     6404     6398       -6     
==========================================
+ Hits        18220    18241      +21     
+ Misses       5770     5747      -23     
Flag Coverage Δ
backend 76.04% <100.00%> (+0.09%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@andypalmi
andypalmi force-pushed the feat/mcp-tools-application-read branch from f5e73f5 to 0024806 Compare July 4, 2026 13:33
@andypalmi andypalmi linked an issue Jul 6, 2026 that may be closed by this pull request
@andypalmi
andypalmi force-pushed the feat/mcp-tools-shared-schemas branch from 8bfb22e to 9742987 Compare July 6, 2026 13:13
@andypalmi
andypalmi force-pushed the feat/mcp-tools-application-read branch from 0024806 to d9a1087 Compare July 6, 2026 16:38
@andypalmi
andypalmi force-pushed the feat/mcp-tools-application-read branch from d9a1087 to ac0cb49 Compare July 6, 2026 22:01
@andypalmi
andypalmi marked this pull request as draft July 30, 2026 08:20
@andypalmi
andypalmi force-pushed the feat/mcp-tools-shared-schemas branch from 103f9ae to 5773bdb Compare August 3, 2026 13:19
Add forge/ee/lib/mcp/schemas.js, a shared module of composable zod
fragments the platform read tools import instead of redefining entity-id
and pagination/search/sort/audit-log query fields in each tool file.

- entity-id params: teamId, applicationId, hostedInstanceId (UUID),
  remoteInstanceId, snapshotId
- query fragments composed per route by spreading only the params the
  backing finder honors: cursorParam/limitParam (basePagination),
  pageParam, searchQuery, sortParams, auditLogFilters
- appendQuery serialises a tool's supported params onto the request URL

The module lives one level above tools/ so the tool loader does not
register it as a tool module.

Closes #7669
@andypalmi
andypalmi force-pushed the feat/mcp-tools-shared-schemas branch from eae081f to e04360f Compare August 3, 2026 14:13
@andypalmi
andypalmi force-pushed the feat/mcp-tools-application-read branch from 3a537c8 to 2182bda Compare August 3, 2026 15:28
@andypalmi
andypalmi marked this pull request as ready for review August 3, 2026 15:48
@andypalmi
andypalmi force-pushed the feat/mcp-tools-application-read branch from 2182bda to d8bb05e Compare August 4, 2026 10:52
@andypalmi
andypalmi force-pushed the feat/mcp-tools-application-read branch from d8bb05e to 03bd44b Compare August 4, 2026 11:00
@andypalmi andypalmi self-assigned this Aug 4, 2026
@andypalmi
andypalmi requested a review from cstns August 4, 2026 12:37
Base automatically changed from feat/mcp-tools-shared-schemas to main August 5, 2026 08:48
Comment thread forge/ee/lib/mcp/tools/applications.js Outdated
Comment thread forge/ee/lib/mcp/tools/applications.js Outdated
Comment thread forge/ee/lib/mcp/tools/applications.js Outdated
Comment thread forge/ee/lib/mcp/tools/applications.js Outdated
Rename platform_list_team_application_statuses to
platform_list_team_instance_statuses and retitle it, since the endpoint
returns the live status of each application's hosted and remote instances
rather than a status of the application itself.

Note that platform_list_application_snapshots also covers remote-instance
snapshots, and list the free-text query filter the audit-log tool accepts.
The cursor and limit paging mechanics are already documented by the shared
pagination schema fields, so the duplicate sentences in the audit-log and
snapshot tool descriptions add nothing. Keep the newest-first note, since
that ordering is not conveyed by the schema.
The MCP response formatter parses every tool response as JSON, so the
audit-log CSV export route (text/csv) could not be returned. Remove the
format argument and always read the audit-log entries.
@andypalmi

Copy link
Copy Markdown
Contributor Author

Testing results of new/edited tools

Local platform context these calls ran against:

  • One team with a single application holding 11 hosted instances (all running) and no application-assigned devices.
  • The application has 70 snapshots across its instances, and an audit log with entries at both application scope and the wider project scope.

This PR adds 2 read tools to applications.js and extends platform_get_application_audit_log; all 3 new/edited tools are exercised below. Payloads show the shape of what came back, with hashids and instance UUIDs redacted as APP_ID SNAPSHOT_ID INSTANCE_ID; structural values (counts, states, events) are verbatim.

platform_list_application_snapshots

Lists the snapshots belonging to an application. Honors limit (truncates the returned array) and cursor (pages from the given snapshot id); the response carries the total count.

Case Input params Verdict Returned payload (overview, redacted)
all {applicationId} PASS {count:70, snapshots:[{id:SNAPSHOT_ID, name, project:{name}}, ...]}
limit {applicationId, limit:3} PASS returns exactly 3 snapshots; count stays 70 (total)
cursor {applicationId, limit:3, cursor:SNAPSHOT_ID} PASS returns the 3 snapshots that follow the given id (paging works from a supplied cursor)
bogus applicationId {applicationId:"zzzzzzzzzz"} PASS {content:{code:not_found}, code:404, isError:true}

Note: the underlying route returns count + snapshots only; it does not emit a meta.next_cursor, so a caller pages by passing the last returned snapshot's id as the next cursor. Not changed by this PR.

platform_list_team_instance_statuses

Lists each application in a team with the live status of its hosted and remote instances. associationsLimit caps how many instances/devices are returned per application.

Case Input params Verdict Returned payload (overview, redacted)
valid {teamId} PASS {count:1, applications:[{id:APP_ID, instances:[{id:INSTANCE_ID, meta:{state:"running", lastStartTime, versions, isDeploying:false}}, ... x11], devices:[]}]}
associationsLimit {teamId, associationsLimit:1} PASS same application, instances array capped to 1
bogus teamId {teamId:"zzzzzzzzzz"} PASS {content:{code:not_found}, code:404, isError:true}

platform_get_application_audit_log (extended)

Reads the application audit log (newest first). The extension adds includeChildren, which combines with scope to pull in descendant entries. Also exercised: cursor/limit, free-text query, and event (single or array) filters.

Case Input params Verdict Returned payload (overview, redacted)
default {applicationId, limit:2} PASS {count:1, log:[{event:"application.created"}]} (application scope)
scope=project + includeChildren {applicationId, limit:2, scope:"project", includeChildren:true} PASS {count:2804, all entries scope.type=project} - descendant entries pulled in
event filter {applicationId, limit:5, event:"application.device.unassigned"} PASS {count:0, log:[]} (no such events on this app)

Conclusion

The 3 new/edited tools in applications.js are verified against their descriptions: snapshot listing with working limit/cursor paging (project:snapshot:list), per-application live instance status with associationsLimit (team:projects:list), and the audit-log read with the new includeChildren plus scope/query/event filters (application:audit-log), including the not-found paths. Backing scopes were already allow-listed, so no permissions change was needed.

@cstns
cstns changed the base branch from main to feat/extend-mcp-tool-feature-set August 26, 2026 07:35
@cstns
cstns merged commit e84adaf into feat/extend-mcp-tool-feature-set Aug 26, 2026
29 checks passed
@cstns
cstns deleted the feat/mcp-tools-application-read branch August 26, 2026 07:37
@cstns
cstns deployed to staging August 26, 2026 07:38 — with GitHub Actions Active
@cstns cstns mentioned this pull request Aug 26, 2026
11 tasks
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.

5.3-a Read tools (phase 1)

2 participants