{"id":51653971,"url":"https://github.com/marianfoo/btp-cf-mcp","last_synced_at":"2026-07-14T07:02:46.860Z","repository":{"id":368834963,"uuid":"1286967715","full_name":"marianfoo/btp-cf-mcp","owner":"marianfoo","description":"MCP server for SAP BTP + Cloud Foundry management (read-only PoC) — inspect/manage your BTP account and CF as yourself via IAS OAuth","archived":false,"fork":false,"pushed_at":"2026-07-02T11:57:35.000Z","size":336,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-02T13:13:22.296Z","etag":null,"topics":["btp","cloud-foundry","mcp","model-context-protocol","sap","sap-btp"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marianfoo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-07-02T08:57:27.000Z","updated_at":"2026-07-02T11:57:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/marianfoo/btp-cf-mcp","commit_stats":null,"previous_names":["marianfoo/btp-cf-mcp"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/marianfoo/btp-cf-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianfoo%2Fbtp-cf-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianfoo%2Fbtp-cf-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianfoo%2Fbtp-cf-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianfoo%2Fbtp-cf-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marianfoo","download_url":"https://codeload.github.com/marianfoo/btp-cf-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianfoo%2Fbtp-cf-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35450066,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-14T02:00:06.603Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["btp","cloud-foundry","mcp","model-context-protocol","sap","sap-btp"],"created_at":"2026-07-14T07:02:46.056Z","updated_at":"2026-07-14T07:02:46.852Z","avatar_url":"https://github.com/marianfoo.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# btp-cf-mcp\n\n**An MCP server that lets an AI assistant inspect and manage your SAP BTP account and Cloud Foundry —\nas *you*.** A user signs in once via IAS; the server then calls the BTP and Cloud Foundry APIs under\nthat person's own identity, so their real roles are enforced and the audit trail shows the real human —\nno shared technical password, no second login. A shared **read-only technical user** mode is also\navailable for headless/automation callers.\n\n\u003e Status: a working **proof-of-concept**, read-only by default. Reads are live-verified on a free-tier\n\u003e BTP account; writes (app lifecycle, service create/delete) execute only when explicitly enabled and\n\u003e only against allowlisted targets. See [Status](#status).\n\n---\n\n## What it is\n\nAn [MCP](https://modelcontextprotocol.io) server (same lineage as [arc-1](https://github.com/arc-mcp/arc-1),\nwhich does this for ABAP) that gives Claude — or any MCP client — a small, safe set of tools over:\n\n- **SAP BTP account** — subaccounts, environments, entitlements (via the `btp` CLI server APIs).\n- **Cloud Foundry** — orgs, spaces, apps, services (via the Cloud Controller v3 API).\n\nThe point of difference is **identity**: the server is its own OAuth authorization server that proxies\nlogin to IAS, seals the user's credential into its own token, and then acts **as that user** on every\ncall — CF enforces their org/space roles, BTP enforces their global-account roles. It reimplements the\n`btp` CLI *server* protocol over plain HTTPS, so there is **no CLI binary** in the container.\n\n## What you can do\n\nReads and writes are **separate tools** so each read tool is honestly `readOnlyHint:true` (hosts\nauto-approve, no confirm friction), and a read-only deployment renders **only** the two Inspect tools:\n\n| Tool | Actions | Notes |\n|---|---|---|\n| **`CFInspect`** (read) | `orgs`, `spaces`, `apps`, `services`, `routes`, `app_detail`, `app_processes` | Cloud Controller v3; as the user or a shared CF token. `app_processes` = instance health/state |\n| **`BTPInspect`** (read) | `subaccount`, `subaccounts`, `global_account`, `environments`, `entitlements`, `subscriptions` | `entitlements` = global-account catalog, or a subaccount's plan assignments if you pass a subaccount |\n| **`whoami`** | — | diagnostic: resolved scopes + token claims |\n| `CFApps` / `BTPServices` (write) | restart/stop/start an app · create/delete service instances | **per-user (OAuth) only**; hidden unless `ALLOW_WRITES=true`; targets must be allowlisted — CFApps resolves the app's **real** space server-side |\n\nA deliberately small surface (fewer tools select more accurately). Every action is defined once in a\n**single-source registry** (`src/registry.ts`); the schema, scopes, MCP annotations, and dispatch all\nderive from it — so growing capability is adding a row, not a tool.\n\n## Use cases\n\n- **\"Which of my apps are running, and is anything crashed?\"** — an AI ops helper over `CFInspect.apps`\n  for a developer, scoped to exactly the spaces they have roles in.\n- **\"What service plans is this account entitled to, and how much quota is left?\"** — `BTPInspect.entitlements`\n  for capacity/licensing questions, without opening the cockpit.\n- **\"List my subaccounts and their environments\"** — a quick BTP-account overview from chat.\n- **Team read-only assistant** — point a shared, **read-only technical user** (Global Account Viewer +\n  Subaccount Viewer) at a support channel so anyone can ask about the landscape, with one auditable identity.\n- **Per-developer accountability** — each developer's assistant logs in as them, so it sees *only* what\n  they're entitled to and every action is attributed to the real person.\n\n## How it works\n\n```\n MCP client ──OAuth (this server IS the auth server, proxying to IAS)──▶ [btp-cf-mcp]\n      │  or  Authorization: Bearer \u003capi-key\u003e                                  │ MCP token = a sealed JWE\n      ▼                                                                       │ holding the user's IAS credential\n   IAS login (browser, once)  ◀───────────────────────────────────────────────┤\n                                  per request: unseal → IAS app-to-app exchange │\n                    ┌───────────────────────────────────────────────────────────┘\n                    ▼ CFInspect                            ▼ BTPInspect\n        CF UAA → Cloud Controller v3 (as you)   btp CLI *server* REST (as you) — no binary\n```\n\n- **Inbound** — the server exposes OAuth (`/authorize` `/token` `/register` + discovery), proxies login to\n  IAS, and issues its own token: a **sealed, audience-bound JWE** of the IAS credential (never a passthrough).\n  DCR is guarded by a **consent gate** so a user always sees which client they're authorizing.\n- **Outbound** — per request it unseals the credential, does the IAS app-to-app exchange, and calls CF\n  (via CF UAA) and BTP (via the CLI-server protocol) **as the user**.\n\nFull design + the hard-won auth details: [docs/guides/per-user-ias-auth-setup.md](docs/guides/per-user-ias-auth-setup.md).\n\n## Two identity models\n\n- **Per-user (\"acts as you\")** — best audit + least-privilege; each user logs in via IAS.\n- **Shared read-only technical user** — one service account (Global Account Viewer + Subaccount Viewer) for\n  headless/API-key callers; simpler, one audited identity.\n\nBoth can run on the **same instance** — an OAuth caller runs per-user, an API-key caller uses the tech user.\nSetup + trade-offs: [docs/guides/admin-deployment.md](docs/guides/admin-deployment.md) → \"Identity models\".\n\n## Safety\n\n- **Read-only by default** (`ALLOW_WRITES=false`); writes need explicit enablement + a fail-closed target\n  allowlist (`ALLOWED_SUBACCOUNTS/ORGS/SPACES`) + per-action `DENY_ACTIONS`.\n- **Scopes** (`read`/`write`/`admin`) prune the tool list — the LLM only sees what the caller may do.\n- **Two authz layers** — the server's scope gate *and* the user's real BTP/CF roles (defense in depth).\n- **Consent gate** on the OAuth proxy (confused-deputy defense); secrets never logged; sealed tokens are\n  audience-bound so they can't be replayed at a sibling service.\n\n## Quick start\n\nDeploy to BTP Cloud Foundry (IAS-first, per-user):\n\n```bash\nnpm ci \u0026\u0026 npm run build                # dist/ is not committed — build before pushing\ncf push btp-cf-mcp                     # or: mbt build \u0026\u0026 cf deploy (secrets via an mtaext OUTSIDE the repo — see mta.yaml)\n# then set the IAS-first config (secrets via cf set-env, never manifest.yml):\ncf set-env btp-cf-mcp SEALING_SECRET \"$(openssl rand -hex 32)\"\ncf set-env btp-cf-mcp IAS_ISSUER https://\u003ctenant\u003e.accounts.ondemand.com\ncf set-env btp-cf-mcp IAS_CLIENT_ID \u003cid\u003e   # + IAS_CLIENT_SECRET, CF_PLATFORM_CLIENT_ID,\ncf set-env btp-cf-mcp CF_UAA_URL ...        #   CF_UAA_URL, CF_API, BTP_GA_SUBDOMAIN, PUBLIC_URL\ncf restage btp-cf-mcp\n```\n\nPoint an MCP client (Claude, `npx @modelcontextprotocol/inspector`) at `https://\u003croute\u003e/mcp` → it\ndiscovers OAuth, you log in via IAS, and tool calls run as you. **Full step-by-step (IAS app, the roles\nthat make reads return data, troubleshooting, caveats): [docs/guides/admin-deployment.md](docs/guides/admin-deployment.md).**\n\n## Status\n\n**Shipped + live-verified** (free-tier BTP account):\n- ✅ IAS-first **per-user** inbound (OAuth proxy) + a signed, browser-bound **consent gate**.\n- ✅ Per-user **Cloud Foundry** (Cloud Controller, as the user) and **BTP account** reads (CLI-server protocol, no binary).\n- ✅ Shared **read-only technical user** mode (username/password login).\n- ✅ Read-only safety gate + scope-based tool pruning; sealing-key rotation; refresh-token rotation; session caching.\n\n- ✅ Read/write-split tool surface (`CFInspect`/`BTPInspect` + write tools) with honest MCP annotations.\n\n- ✅ Writes: CF app lifecycle (restart/stop/start) + Service Manager create/delete — off by default,\n  fail-closed target allowlists, and CFApps gates on the app's **server-resolved** space (never a\n  caller-supplied value).\n\n**PoC boundaries:**\n- ⏳ Async job polling for service create/delete is manual (verify via `BTPInspect.service_instances`).\n- ⏳ Mapping IAS groups → scopes and an MTA-only deploy are future work.\n\n## Documentation\n\n- [docs/guides/admin-deployment.md](docs/guides/admin-deployment.md) — deploy + configure (start here)\n- [docs/guides/connect-mcp-clients.md](docs/guides/connect-mcp-clients.md) — connect Copilot / Claude Desktop / Codex / VS Code / Cursor\n- [docs/guides/per-user-ias-auth-setup.md](docs/guides/per-user-ias-auth-setup.md) — the IAS per-user auth recipe\n- [ROADMAP.md](ROADMAP.md) — what works today vs what's planned · [CONTRIBUTING.md](CONTRIBUTING.md) — dev setup\n- [docs/README.md](docs/README.md) — full docs index · [AGENTS.md](AGENTS.md) — codebase guide for AI agents\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarianfoo%2Fbtp-cf-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarianfoo%2Fbtp-cf-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarianfoo%2Fbtp-cf-mcp/lists"}