MCP tools
Reference
Greenlight exposes its functionality to coding agents as a fixed catalog of MCP tools. This page is the canonical reference: every tool, what it takes, what it returns, and a small example.
The conceptual model is in The agent protocol. This page assumes you know what MCP is and how an agent calls a tool.
Catalog
Section titled “Catalog”Every tool is served by the greenlight MCP server and grouped by area. Jump to a group:
| Area | Tools |
|---|---|
| App lifecycle | registerApp · getRepoAccess · getApp · listApps · addCoOwner · removeCoOwner |
| Marketplace | discoverApps · requestAppAccess |
| Context (Knowledge) | knowledgeList · knowledgeGet · knowledgeSearch · knowledgePropose |
| Policy | getPolicies |
| Integrations | listGrantableIntegrations · requestCredentialAccess · getPermissions |
| Environment variables | envList · envSet · envRemove |
| Local development | approveCliSession · inspectAppDb · inspectIntegrationApi · inspectAppBlob |
| Pipeline & operations | createPullRequest · mergePullRequest · getPipelineRun · getLogs · getMetrics · getMetricsSeries · getAppDiagnostics · curlApp · getAppPreviewUrl |
Conventions
Section titled “Conventions”- Tool names are flat camelCase (no dots) and served by the
greenlightMCP server. Related tools share a name prefix (e.g.env*,knowledge*,inspect*). - Authorization is bound to the user the agent session is authenticated as. The agent cannot do anything the user couldn’t.
- Environment — Each app has one environment. Tools that accept
envdefault tosharedwhen omitted. - Infrastructure is declarative. Workloads, resources (Postgres, blob), and integration grants are declared in
greenlight.ymland applied by the merge-time reconciler — there is no MCP tool that provisions them. The catalog covers app lifecycle, env-var values, the pull-request flow, local development, and observability; the declared shape is read back throughgetApp. - Env writes take effect on deploy.
envSet/envRemovestore the value and returnstatus: "complete"; the running app picks up the change on its next deploy. - No credential ever leaves Greenlight. No tool returns an upstream credential, a vault value, or a proxy/AI key. Tools that touch real data either run inside the control plane and return only results (
inspect*), or deliver values to the laptop through the pairedgreenlightCLI — never through an MCP response. - Errors follow the error envelope.
codeis stable; messages are not. - Idempotency is supported on mutating tools that accept an
idempotency_key. Repeated calls with the same key return the original response. - Pagination is cursor-based; see Errors & pagination.
App lifecycle
Section titled “App lifecycle”registerApp
Section titled “registerApp”Creates a new app as a scaffold — no cloud provisioning. It writes the apps row, the single shared environment row, and the SCM repository seeded with .gitignore, the Greenlight pipeline workflow, and a greenlight.yml carrying the app’s app_id, a docs.* block, and commented-out scaffold for workloads, resources, grants, and env. No Dockerfile is seeded — the agent authors it for the app’s stack in the first code PR. Workloads, resources, grants, and all infrastructure come from the first PR that declares them in greenlight.yml and merges. Registration is resumable and idempotent: calling it twice for the same slug resumes rather than creating a second app.
Input
{ "name": "Expense Tracker", "slug": "expense-tracker", "type": "server", "description": "Quick reimbursement tracker for the finance team."}Output
{ "app_id": "app_k9x2m3p", "slug": "expense-tracker", "repo_full_name": "contoso/gl-app-expense-tracker", "clone_url": "https://github.com/contoso/gl-app-expense-tracker", "token_expires_at": "2026-03-12T15:08:11Z", "registration_state": "complete", "resumed": false}getRepoAccess
Section titled “getRepoAccess”The way back into an existing project. Mints a fresh one-hour SCM token scoped to the app’s repo, so the agent can clone or pull. Called at the start of any session that needs to push code to an already-registered app, and again mid-session if the token is about to expire.
Input
{ "app_id": "app_k9x2m3p" }Output
{ "clone_url": "https://github.com/contoso/gl-app-expense-tracker", "token": "ghs_…", "clone_command": "git clone https://x-access-token:ghs_…@github.com/contoso/gl-app-expense-tracker.git", "authenticated_clone_url": "https://x-access-token:ghs_…@github.com/contoso/gl-app-expense-tracker.git", "expires_at": "2026-03-12T16:08:11Z", "repo_name": "gl-app-expense-tracker", "repo_full_name": "contoso/gl-app-expense-tracker"}The token is a GitHub App installation token: it authenticates as the x-access-token user spliced into the HTTPS URL. clone_command and authenticated_clone_url are ready-to-run forms — the agent clones and pushes with those (or splices token into clone_url itself) rather than the gh CLI, which the agent’s session is usually not authenticated for.
getApp
Section titled “getApp”Returns the current state of an app: the app row, its shared-environment summary, the declared manifest (resources, workloads, grants, env) projected from the last-merge SHA, per-grant approval status, the full env contract (user + managed names), and the latest pipeline run. Returns identifiers and metadata only — never raw manifest YAML, never env-var values.
listApps
Section titled “listApps”Lists the caller’s apps, most recently deployed first (never-deployed apps last) — a citizen developer sees the apps they own or co-own; IT admin roles see every app in the organization. Cursor-paginated (limit 1–100, default 20).
addCoOwner / removeCoOwner
Section titled “addCoOwner / removeCoOwner”Add or remove a co-owner on an app — used when a citizen developer says “let Bob help me with this.” Both take app_id, user_email, and an audit reason. The target must have logged into Greenlight at least once; otherwise addCoOwner returns user.not_found with the org login URL in next_steps.
Marketplace
Section titled “Marketplace”discoverApps
Section titled “discoverApps”The agent-facing counterpart to the dashboard Marketplace tab — browse every live, discoverable app in the org, not just the ones the caller already owns or co-owns. Cursor-paginated (limit 1–100, default 20), with optional slug (exact) and name_query (substring) filters. An app the caller can already open carries its deployment_url; one they can’t carries the same catalog-safe fields with deployment_url withheld and viewer_has_access: false — call requestAppAccess to ask for it.
Input
{ "name_query": "expense" }Output
{ "items": [ { "app_id": "app_k9x2m3p", "slug": "expense-tracker", "name": "Expense Tracker", "owner_email": "avery@contoso.com", "owner_name": "Avery Chen", "deployment_url": null, "viewer_has_access": false, "access_request_status": null } ], "next_cursor": null}requestAppAccess
Section titled “requestAppAccess”Requests the calling user’s own access to an app found via discoverApps or listApps — the imperative counterpart of requestCredentialAccess, but for a person’s access to an app instead of an integration credential. The signed-in user is always the one requesting; there’s no requesting on someone else’s behalf. Writes the same request the dashboard’s request-access form writes, with the same idempotency (an open request returns as-is) and re-request behavior (a denied or revoked request re-opens as pending). IT or the app’s owner approves, denies, or revokes from the dashboard — there is no agent decision tool.
Input
{ "slug": "expense-tracker", "reason": "Need to check my reimbursement status" }Output
{ "grant_id": "5b8f0c2e-…", "app_id": "app_k9x2m3p", "slug": "expense-tracker", "name": "Expense Tracker", "status": "pending", "requested_at": "2026-07-03T09:12:44.180Z", "owner_email": "avery@contoso.com", "owner_name": "Avery Chen"}Resources & workloads
Section titled “Resources & workloads”Resources (Postgres, blob) and workloads (the app’s web server) are declared in greenlight.yml, not provisioned through MCP. The agent edits the resources: and workloads: blocks, opens a PR, and on merge the reconciler provisions the resources, renders the Kubernetes manifests, and rolls out the deploy. There is no resource.add tool; the declared and live state is read back through getApp, and merge-time provisioning outcomes surface through getPipelineRun.
Context (Knowledge)
Section titled “Context (Knowledge)”knowledgeList
Section titled “knowledgeList”Lists entry summaries for a scope.
Input
{ "scope": "org" | "integration" | "app", "integration": "snowflake", "app_id": "app_k9x2m3p", "tags": ["data-modeling"], "cursor": "..."}Output
{ "items": [ { "id": "kn_pf2", "scope": "app", "topic": "architecture", "title": "App architecture", "version": 4, "updated_at": "2026-03-12T14:08:11Z" } ], "next_cursor": null}Catalog and Custom integrations both start with no integration Knowledge; your team authors entries as it learns the source. If IT makes an integration inactive, all four Knowledge tools hide or reject its integration-scope entries for every agent role while the preserved content remains editable in the dashboard.
knowledgeGet
Section titled “knowledgeGet”Returns one entry’s full body.
Input
{ "id": "kn_pf2" }or
{ "scope": "app", "app_id": "app_k9x2m3p", "topic": "architecture" }Output
{ "id": "kn_pf2", "scope": "app", "topic": "architecture", "title": "App architecture", "body_md": "## Overview\n\nThis app...", "version": 4, "updated_at": "2026-03-12T14:08:11Z", "last_editor_kind": "agent"}knowledgeSearch
Section titled “knowledgeSearch”Full-text search over titles and bodies.
Input
{ "query": "snowflake warehouse", "scope": "integration" }Output
{ "items": [ { "id": "kn_a1", "title": "Snowflake warehouses we use", "scope": "integration", "snippet": "...the `ANALYTICS_PROD` warehouse..." } ], "next_cursor": null}knowledgePropose
Section titled “knowledgePropose”The agent write path. Always writes to the proposal queue; never mutates entries directly.
Input
{ "scope": "app", "app_id": "app_k9x2m3p", "topic": "architecture", "title": "App architecture", "body_md": "...", "rationale": "Discovered a clean way to split the cron job from the API.", "base_version": 3}Output
{ "proposal_id": "kp_xyz", "status": "pending"}Policy
Section titled “Policy”getPolicies
Section titled “getPolicies”Returns the active policy bundle for the org. Agents call this before generating code to know the rules.
Input
{ "kind": "approved-base-images" }kind is optional; omit to get the full bundle.
Output
{ "policies": [ { "id": "approved-base-images", "kind": "deny_if", "version": 12, "body": { "match": { /* … */ } } } ]}Integrations
Section titled “Integrations”Integration grants are declared in greenlight.yml, not requested through MCP. On merge, Greenlight diffs the declared grants: entries against the app’s permissions and queues IT review for any that are not auto-approved.
Each grant names the integration and the credential slug IT registered — a stable handle, not a read/write/access enum:
grants: - integration: snowflake-prod credential: analytics-read reason: Read the sales mart for the dashboard.Each integration carries an auth_mode and a delivery_mode; see Data brokering for what they mean.
listGrantableIntegrations
Section titled “listGrantableIntegrations”Lists the available integrations your org has registered and the credential slugs each exposes — call it before requesting access either way: as grants: targets for an app manifest, or as requestCredentialAccess targets for your own personal access. For each integration it returns the identity model (auth_mode), how the credential reaches the app (delivery_mode), and the catalog entry it was registered from (catalog_key, null for a Custom integration). For each credential it returns a paste-ready manifest_grant_example and a request_example (the personal-access call), your own current grant status on it (caller_grant_status), and a plain-language label for what to obtain (credential_kind) with a docs_link to the upstream’s own instructions. Read-only, cursor-paginated, scoped to your org. Integrations IT has made inactive are omitted and behave as not found when a stale slug is used in a grant request. Never returns vault keys, credential values, or upstream tokens.
Input
{ "integration": "snowflake-prod", "cursor": "...", "limit": 20 }All fields are optional; omit integration to list every registered integration.
Output
{ "items": [ { "integration": "snowflake-prod", "name": "Snowflake (Prod)", "catalog_key": "snowflake", "delivery_mode": "injected", "env_var_name": "SNOWFLAKE_API_KEY", "base_url": "https://acme.snowflakecomputing.com", "auth_mode": "service_account", "credentials": [ { "slug": "analytics-read", "scope": "Read access to the analytics warehouse", "credential_kind": "Snowflake programmatic access token", "docs_link": "https://docs.snowflake.com/en/user-guide/key-pair-auth", "configured": true, "approval_mode": "manual", "manifest_grant_example": { "integration": "snowflake-prod", "credential": "analytics-read", "yaml": "grants:\n - integration: snowflake-prod\n credential: analytics-read\n" }, "request_example": { "integration": "snowflake-prod", "credential_slug": "analytics-read", "call": "requestCredentialAccess({ integration: 'snowflake-prod', credential_slug: 'analytics-read', reason: '<why the user needs this>' })" }, "caller_grant_status": "none" } ], "usage_note": "Injected delivery: once IT approves the grant, read the credential from process.env.SNOWFLAKE_API_KEY in the deployed app and call the upstream directly." } ], "next_cursor": null}catalog_keynames the catalog entry the integration was registered from, or isnullfor a Custom integration (registered by hand). For Custom integrations,credential_kindis empty anddocs_linkmay benull.env_var_nameis populated only whendelivery_modeis"injected"— it’s the name the credential is delivered under at deploy. Proxied integrations leave itnull; the app reaches them through the proxy base URL instead.base_urlis the registered upstream host the proxy calls for this integration — use it to recognize when an existing integration already covers an API you were about to ask for. It’snullfor a connected database, which has no HTTP base URL.- A credential marked
configured: falseis listed but not yet servable — a grant naming it cannot be approved until IT finishes registration. approval_modeis"auto"(the grant activates on merge) or"manual"(IT reviews it in the queue before the runtime value is delivered).caller_grant_statusis your own personal grant on this credential —none,pending,granted,denied, orrevoked— so an agent never re-requests blindly.- A
greenlight.ymlgrant or Knowledge lookup naming an integration that doesn’t exist or is inactive gets anot_founderror listing the valid available slugs — the same set this tool returns — so a mistyped or abbreviated name (e.g.fmpforfinancial-modeling-prep) is correctable from the error alone without disclosing inactive integrations.
requestCredentialAccess
Section titled “requestCredentialAccess”Requests personal access to an integration credential for the signed-in user — for local work with no app, repo, or manifest. This is the imperative counterpart of an app’s declarative grants: block: an app’s access is declared in its manifest and activates at merge; a person’s access is requested with this call and reaches the same governed proxy under their own identity. The result is granted immediately when IT has set the credential to auto-approve, otherwise pending in IT’s review queue. Re-requesting after a denial or revocation re-opens the request as pending — it never overrides IT’s decision. Every request is recorded, including ones IT later denies.
Input
{ "integration": "snowflake-prod", "credential_slug": "analytics-read", "reason": "Explore the sales mart for a local dashboard" }Output
{ "grant_id": "5b8f0c2e-…", "integration": "snowflake-prod", "credential_slug": "analytics-read", "status": "granted", "requested_at": "2026-07-03T09:12:44.180Z", "policy_note": "auto-granted per credential approval mode"}Once granted, greenlight run (with no --app flag) delivers the access — see Local development. There is no dashboard form for this: requests come from the agent or CLI; the dashboard is where IT reviews them.
getPermissions
Section titled “getPermissions”Lists integration grants for the app — declared grants from the manifest at the last-merge SHA, joined with approval status. Read-only. For each granted credential it also returns delivery_mode, which tells the agent how the integration runs locally: a granted integration is live (proxied through a minted token, or injected raw in-process); only user-delegated sources are fixture-only. An injected grant also carries its target env_var_name — including while status is still "pending" (a manual-approval grant), so the agent can see the name it will get without being told a value is already live before IT approves and the app redeploys.
Input
{ "app_id": "app_k9x2m3p" }Output
{ "items": [ { "integration": "snowflake-prod", "credential": "analytics-read", "declared_in_manifest": true, "status": "approved", "delivery_mode": "injected", "env_var_name": "SNOWFLAKE_API_KEY" } ]}Environment variables
Section titled “Environment variables”envList / envSet / envRemove
Section titled “envList / envSet / envRemove”Manage env-var values on the app’s shared environment. Values live in the customer’s Key Vault at apps/<app-id>/env/shared/<name>; Postgres stores metadata only. The names that reach the pod are governed by greenlight.yml (the env: block, plus managed names derived from resources: and grants:).
set/remove— store the vault value and the metadata row, then return{ plan, executed_ops, status, note }. They do not restart the running app; it picks up the change on its next deploy (thenotefield restates this).sensitive: truemakes the value write-once — it is never returned after creation. Reserved system names (e.g.DATABASE_URL) are rejected.setrequires areasonfor the audit log.list— returns the full env contract: user-declared names (with vault presence) and derived managed names. Plain values are returned only whenreveal: true; sensitive values are never returned.
await envSet({ app_id: 'app_k9x2m3p', name: 'APPROVAL_SECRET', value: '…', env: 'shared', sensitive: true, reason: 'Signing secret for the approvals webhook.',});See App environment variables for reserved names, the plain-vs-sensitive model, and the MISSING_ENV_VALUE deploy gate.
Local development
Section titled “Local development”The agent develops the app on its own machine without ever holding an upstream credential. Two surfaces serve this, and neither puts a secret in an MCP response: the bundled greenlight CLI runs the app with real values delivered straight into the process, and the inspect* tools read deployed data inside the control plane and return only results. Whether a given integration is live locally or fixture-only is IT’s choice, set per credential. The full loop is in The agent protocol.
approveCliSession
Section titled “approveCliSession”Signs the bundled greenlight CLI in as the caller, over the already-authenticated MCP session — no separate browser login. The CLI ships inside the plugin, so there’s nothing to download. The developer runs greenlight pair, which prints a short code; the agent passes it here; the server mints the CLI its own Greenlight credential — bound to the caller (owner/co-owner) under their normal RBAC, the same credential the CLI uses for every command — and hands it to the CLI out of band, never in this response. The code is single-use. Returns no secret to the agent.
Input
{ "code": "ABCD-1234" }Output
{ "session_id": "cli_sess_7h2", "app_scope": ["app_k9x2m3p"], "expires_at": "2026-03-12T18:08:11Z"}Once paired, the agent runs code with greenlight run, in one of two explicit modes. App mode — greenlight run --app <app_id> -- <your dev command> — resolves the app’s environment contract and grants (the same ones the deployed pod runs on) and injects the values into the running process; there is no credentials file on disk. User mode — greenlight run -- <cmd> with no --app — runs on the signed-in user’s own personal grants instead (see requestCredentialAccess), for local work with no app at all. Either way, proxied integrations are reached through the same public proxy URL the deployed app uses, authenticated with a short-lived token the CLI mints from its session; the upstream secret stays in Greenlight exactly as it does in production. Granted injected credentials are delivered as their raw value in-process — every delivery is audited under the developer’s name. The app’s own Postgres runs as a local fixture database — use inspectAppDb to read deployed rows.
inspectAppDb
Section titled “inspectAppDb”Runs one read-only SQL statement against the app’s own provisioned Postgres, executed inside the control plane against the vaulted credential. Returns columns and a capped set of rows — never the credential. Always available for the app’s own database, so the agent can learn the real schema and data before writing code. Audited with the calling user.
Input
{ "app_id": "app_k9x2m3p", "statement": "select status, count(*) from expenses group by 1", "params": []}Output
{ "columns": [ { "name": "status", "type": "text" }, { "name": "count", "type": "int8" } ], "rows": [["approved", 142], ["pending", 17]], "row_count": 2, "truncated": false}inspectIntegrationApi
Section titled “inspectIntegrationApi”Performs one HTTP request against a granted proxied integration, through the same grant check, credential swap, and audit path as the data proxy, with the developer’s session as the principal. Returns the response — never the upstream credential. Always available for a granted proxied integration. Injected integrations are not reachable here (they have no proxy backend); investigate those through Knowledge, a greenlight run against the granted raw value, or fixtures.
Input
{ "app_id": "app_k9x2m3p", "integration": "snowflake-prod", "method": "POST", "path": "/api/v2/statements", "body": { "statement": "select current_warehouse()" }}Output
{ "status": 200, "headers": { "content-type": "application/json" }, "body": { "data": [["ANALYTICS_PROD"]] }, "truncated": false}inspectAppBlob
Section titled “inspectAppBlob”Inspects the app’s own provisioned blob container, executed inside the control plane — never returns a SAS or credential. Three actions: list (prefix filter, capped count), read (one blob’s bytes, size-capped; text/JSON inline, otherwise base64), and head (metadata only). Always available for the app’s own storage. Audited with the calling user.
Input
{ "app_id": "app_k9x2m3p", "action": "list", "prefix": "exports/" }Output
{ "items": [ { "key": "exports/2026-03.csv", "size": 20480, "content_type": "text/csv", "last_modified": "2026-03-12T14:08:11Z" } ], "truncated": false}Pipeline & operations
Section titled “Pipeline & operations”createPullRequest / mergePullRequest
Section titled “createPullRequest / mergePullRequest”Open and merge pull requests on the app’s repo. Direct pushes to main are blocked by branch protection; every change goes through a PR and the Greenlight Review and Policy Check (scanners + policy). The agent confirms that check passed via getPipelineRun, then calls mergePullRequest with the app id, PR number, and the exact head commit SHA it observed pass (expected_head_sha); merging applies the manifest and triggers the deploy. The call fails closed with a structured error — never falling through to the SCM provider’s merge API — if the PR has moved to a new head since, or if that head has not passed review.
getPipelineRun
Section titled “getPipelineRun”The single pipeline read tool. It returns one run with its per-check verdicts and is the agent’s wait primitive after pushing a branch or opening a PR — it can long-poll server-side up to max_wait_seconds. Pass detail: "full" to enrich every check with structured remediation detail (failing file, line, rule, and a suggested fix) and, where available, a tail-capped log snapshot — so there’s no separate failure tool; the detail lives on each check. A failed deploy check also carries a blocker: whether the failure is a platform issue the agent should not try to fix in app code (owner: "operator", e.g. the cluster is out of schedulable capacity) or an app-side issue it can act on (owner: "agent"), plus a one-line explanation. Wait by commit_sha when the exact head must be confirmed — waiting by pull_request_number resolves to the newest recorded run, which can lag the current head after a force-push.
getLogs / getMetrics / getMetricsSeries / getAppDiagnostics / curlApp / getAppPreviewUrl
Section titled “getLogs / getMetrics / getMetricsSeries / getAppDiagnostics / curlApp / getAppPreviewUrl”Runtime observability and smoke checks against the deployed shared environment. getLogs returns a bounded, paginated window of the pod’s merged stdout/stderr; getMetrics returns the most recent per-app CPU/memory/restart snapshot; getMetricsSeries returns a downsampled CPU or memory history over a window — bucketed averages plus a min/max/avg/p95 summary — so the agent can judge a trend without reading every sample; getAppDiagnostics returns one structured health snapshot (pod phase, restart reason, probe state, resource pressure, the env contract with values masked, dependency reachability, and freshness) — the consolidated “why is my deployed app misbehaving?” read; curlApp makes an authenticated server-side request into the deployed app with the same user and app-access decision as the SSO boundary, so the agent can confirm the app actually responds for a real authorized user after deploy. If the Service cannot complete a response, it returns app.unreachable; inspect details.hit_app, then call getAppDiagnostics and getLogs.
getAppPreviewUrl covers what curlApp can’t: seeing the app. It mints a one-time URL the agent opens in its own browser tooling (IDE preview pane, headless browser) to render pages, exercise client-side code, and capture screenshots. The embedded token is single-use, expires in five minutes, and is exchanged on first navigation for a short-lived session confined to that one app’s hostname — the session carries the agent user’s real identity, so access control and the audit trail behave exactly as if that person had signed in. SSO enforcement is never bypassed or weakened.
The two are complementary, and they even take different routes: curlApp goes server-side straight to the app inside the cluster, while a preview URL travels the full public path — DNS, TLS, and the SSO-enforcing ingress. When one succeeds and the other fails, that difference tells the agent whether the app or the edge is the problem. Agents default to curlApp for response checks (no credential ever leaves the platform) and mint a preview URL when verification needs a real browser. The CLI twin is greenlight curl --app <id> --path <path>; request headers and bodies are read from --headers-file, stdin, or --body-file, never placed directly in argv.
Feedback
Section titled “Feedback”submitFeedback
Section titled “submitFeedback”Files a concise Greenlight platform-experience report — a platform bug, recurring friction, or a concrete improvement idea — for the Greenlight platform team. It takes a category (bug / friction / suggestion / other), a one-line title, and a Markdown body_md (optionally an app_id and a small allowlisted context with the agent runtime, OS, plugin version, and related request_ids). The report is recorded with its source and calling surface derived server-side, attributed to the signed-in user, and returns a feedback id. Body content is treated as untrusted (capped, rendered inert on the dashboard) and submission is rate-limited per user, so reports should summarize the platform interaction — never secrets, env values, tokens, or verbatim sensitive content. The CLI twin is greenlight feedback (body via stdin or --body-file). Org admins review submissions on the dashboard Feedback tab, alongside reports filed by dashboard users through the shell “Send feedback” dialog.
Skills
Section titled “Skills”getBuilderSkill
Section titled “getBuilderSkill”Returns the full markdown of the universal Greenlight Builder Skill — the core greenlight Skill by default, or a focused Skill (connected-databases, platform-feedback) by skill name — byte-identical to the Skill file bundled in the plugin. Use it to re-fetch the Skill when the plugin skill isn’t loaded, after a context compaction, or when only MCP/CLI is reachable. An unrecognized skill name returns a skill.not_found error. This is a narrow, authenticated read of the same universal bytes every installation ships — not a per-org generation endpoint. The CLI twin is greenlight skill / greenlight skill show [--name <skill>].