{"ref":"artifact:marianfoo-btp-cf-mcp","page":"/artifacts/marianfoo-btp-cf-mcp","json":"/artifacts/marianfoo-btp-cf-mcp.json","generated":"2026-10-26","drafted_with_ai":true,"entity":{"id":"marianfoo-btp-cf-mcp","name":"btp-cf-mcp","artifact_type":"mcp-server","ecosystem":"btp","domain":"operations-and-runtime","secondary_domains":["ai-and-agents"],"origin_ring":"independent","use_as":"starting-point","description":{"one_line":"An MCP server over an SAP BTP account and its Cloud Foundry runtime that acts as the person who logged in, so their own global-account and space roles decide what an agent can see.","short":"MCP server for SAP BTP and Cloud Foundry acting as the logged-in user","what_it_solves":"An assistant asked which applications are running, or what a subaccount is entitled to, normally needs a technical user with rights nobody wants to hand it. This is its own OAuth authorization server: it proxies login to SAP Cloud Identity Services, seals the user's credential into an audience-bound JWE of its own, and on every call unseals it, does the app-to-app exchange and calls Cloud Controller v3 and the `btp` CLI server protocol as that user, so the audit trail names the real person. Reads and writes are separate tools, which is what lets each read tool declare `readOnlyHint:true` and a read-only deployment render only `CFInspect` and `BTPInspect`. `CFInspect` covers orgs, spaces, applications, services, routes and instance health; `BTPInspect` covers subaccounts, the global account, environments, entitlements and subscriptions. A shared read-only technical user is the second identity model, for headless callers with an API key, and both run on one instance. It reimplements the `btp` CLI server protocol over HTTPS, so no CLI binary sits in the container, and it is deployed to Cloud Foundry rather than run from npm.","to_build_on_it":"Standing one up is configuration before code: an SAP Cloud Identity Services application, a sealing secret and the Cloud Foundry and global-account settings have to be in place before a tool returns data, and writes stay hidden until `ALLOW_WRITES=true` and a fail-closed allowlist names the subaccounts, orgs and spaces they may touch. The maintainer marks what is not finished: polling the asynchronous job behind a service create or delete is manual, and mapping identity-provider groups to scopes and an MTA-only deploy are future work. What would transfer to another server is the single-source registry, where every action is defined once in `src/registry.ts` and the schema, scopes, MCP annotations and dispatch all derive from it, so growing the surface is adding a row rather than writing a tool."},"links":{"repo":"https://github.com/marianfoo/btp-cf-mcp"},"identity":{"author":"Marian Zeis","license":"MIT"},"source_available":true,"compat":{"runtimes":["node"],"deployment":["cf"]},"type_properties":{"runs":{"value":["central-server"],"sources":[{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, Quick start","checked":"2026-09-18","quote":"Point an MCP client (Claude, `npx @modelcontextprotocol/inspector`) at `https://<route>/mcp` → it discovers OAuth, you log in via IAS, and tool calls run as you."}]},"transports":{"value":["http"],"sources":[{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, Quick start","checked":"2026-09-18","quote":"Point an MCP client (Claude, `npx @modelcontextprotocol/inspector`) at `https://<route>/mcp`"}]},"auth":{"value":["oauth","api-key"],"sources":[{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, How it works","checked":"2026-09-18","quote":"**Inbound** — the server exposes OAuth (`/authorize` `/token` `/register` + discovery), proxies login to IAS, and issues its own token: a **sealed, audience-bound JWE** of the IAS credential (never a passthrough)."},{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, Two identity models","checked":"2026-09-18","quote":"Both can run on the **same instance** — an OAuth caller runs per-user, an API-key caller uses the tech user."}]},"read_only":{"value":true,"source":{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, Safety","checked":"2026-09-18","quote":"**Read-only by default** (`ALLOW_WRITES=false`); writes need explicit enablement + a fail-closed target allowlist (`ALLOWED_SUBACCOUNTS/ORGS/SPACES`) + per-action `DENY_ACTIONS`."}},"guardrails":[{"source":{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, Safety","checked":"2026-09-18","quote":"**Scopes** (`read`/`write`/`admin`) prune the tool list — the LLM only sees what the caller may do."}},{"source":{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, Safety","checked":"2026-09-18","quote":"**Two authz layers** — the server's scope gate *and* the user's real BTP/CF roles (defense in depth)."}},{"source":{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, Safety","checked":"2026-09-18","quote":"**Consent gate** on the OAuth proxy (confused-deputy defense); secrets never logged; sealed tokens are audience-bound so they can't be replayed at a sibling service."}},{"source":{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, Status","checked":"2026-09-18","quote":"CFApps gates on the app's **server-resolved** space (never a caller-supplied value)."}}]},"provides":[{"capability":"capability:mcp-servers","what_it_does":"Exposes an SAP BTP account and its Cloud Foundry runtime to an agent as two read tools, a `whoami` diagnostic and two write tools, under the caller's own identity, so the platform's existing role checks are what limit the answer.","sources":[{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README","checked":"2026-09-18","quote":"A user signs in once via IAS; the server then calls the BTP and Cloud Foundry APIs under that person's own identity, so their real roles are enforced and the audit trail shows the real human"},{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, What you can do","checked":"2026-09-18","quote":"Reads and writes are **separate tools** so each read tool is honestly `readOnlyHint:true` (hosts auto-approve, no confirm friction), and a read-only deployment renders **only** the two Inspect tools:"}]}],"requires":[{"ref":"artifact:btp-cloud-foundry-runtime","for":"Where the server itself is deployed, and one of the two APIs it reads: it is pushed as a Cloud Foundry application and calls Cloud Controller v3.","requirement":"required","sources":[{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, Quick start","checked":"2026-09-18","quote":"Deploy to BTP Cloud Foundry (IAS-first, per-user):"}]}],"maintainers":["actor:marianfoo"],"lineage":[{"target":"artifact:arc-mcp-arc-1","kind":"inspired-by","source":{"url":"https://github.com/marianfoo/btp-cf-mcp","title":"marianfoo/btp-cf-mcp — README, What it is","checked":"2026-09-18","quote":"An [MCP](https://modelcontextprotocol.io) server (same lineage as [arc-1](https://github.com/arc-mcp/arc-1), which does this for ABAP)"}}],"provenance":{"discovered_via":[{"source":"source:github","channel":"marianfoo"}],"first_seen":"2026-09-18"},"history":[{"date":"2026-09-18","field":"entry","from":null,"to":"created","reason":"Read out of the marianfoo account listing. Entered as a starting-point, since the maintainer's own status line calls it \"a working proof-of-concept\", so its boundaries sit in description.to_build_on_it rather than in a warning. capability:mcp-servers already reads core-only on the BTP door because every provider there is SAP-published; this is an independent one, which is a reading the capability will have to move."}],"drafted_with_ai":true,"contributors":["actor:marianfoo"]},"effective_normative_relations":[],"readings":{"liveness":[{"label":"Maintenance","tier":"unknown","evidence":"no release data"},{"label":"Continuity","tier":"fair","evidence":"one contributor, personally owned"},{"label":"Repository","tier":"good","evidence":"pushed 2026-10, not archived"}],"compatibility":[{"label":"Declared for","tier":"unknown","evidence":"no BTP release lines in the atlas"},{"label":"Survived majors","tier":"unknown","evidence":"no BTP release lines in the atlas"},{"label":"Maintainer's CI","tier":"good","evidence":"test green, 2026-07-02"}],"practice":[{"label":"Tests","tier":"good","evidence":"10 test files"},{"label":"Docs","tier":"good","evidence":"docs/ with 15 pages, README 9 KB"},{"label":"Changelog","tier":"fair","evidence":"none in the repo"}],"reach":[{"value":null,"unit":"installs/week"},{"value":2,"unit":"watching"}]},"signals":{"crawled_at":"2026-10-25","npm":"not published under this name","stars":2,"forks":1,"open_issues":10,"archived":false,"pushed_at":"2026-10-23","license_spdx":"MIT","org_owned":false,"default_branch":"main","created_at":"2026-07-02T08:57:27Z","open_prs":10,"tree_truncated":false,"test_files":10,"workflows":1,"other_ci":false,"readme_bytes":9061,"docs_files":15,"changelog":false,"license_file":true,"dts_files":0,"first_commit":"2026-06-30","last_commit":"2026-07-02","commits":10,"contributors":1,"ci_status":"success","ci_run_at":"2026-07-02","ci_workflow":"test","ci_event":"push","readme_path":"README.md","readme_sha":"d6bbbcc2b677da6eab15edd1cdbe2dc292edc277","repo_read":"2026-10-25"},"edges":{"maintainers":[{"ref":"actor:marianfoo","name":"Marian Zeis","json":"/actors/marianfoo.json"}],"contributors":[{"ref":"actor:marianfoo","name":"Marian Zeis","json":"/actors/marianfoo.json"}],"explained_by":[],"alternative_to_this":[],"needed_by":[],"available_via":[],"parts":[],"add_ons":[],"answered_through_parts":[]}}