MCP Gateway API
API reference for the Fabric MCP Gateway — endpoint details, authentication, tools, and authority management.
The Fabric MCP Gateway exposes a single endpoint that implements the MCP 2025-03-26 Streamable HTTP transport. It works with any MCP-compatible client.
Endpoint
POST https://your-fabric.com/api/mcp-gateway/projects/<project-id>A project has its own gateway URL, and a connection made at it reaches that
project and nothing else: the tools are the project's own (the instruction,
feature, document, context and knowledge tools, with projectId optional and
defaulting to the project), and no organization-wide tool or connected server is
offered or callable. The organization-wide endpoint, POST https://your-fabric.com/api/mcp-gateway, serves the connections made before
projects had their own URL.
Authentication
Include one of the following:
| Method | Header | Format |
|---|---|---|
| Signed-in agent (recommended) | Authorization | Bearer fat_…, an OAuth 2.1 access token the client obtains by signing in |
| API Key | Authorization | Bearer fab_xxxx_xxxxxxxxxx or Bearer org_… |
| Organization context | X-Organization-Id | Organization ID string (organization-wide endpoint only; not honoured for a signed-in agent, which is bound to what was approved, and ignored at a project's URL, where the project names the organization) |
A signed-in agent's token is issued for one resource and works only there. A
token issued for a project works at that project's URL and nowhere else; an
organization-wide token works at the organization-wide URL; a token issued for
the REST API works at neither gateway URL. A client asks for the resource by
sending it as the resource parameter of its authorization and token requests,
and a project URL refuses a sign-in that does not name the project.
API keys and browser sessions are accepted at a project's URL after a live check that the key's owner can read the project, and the session is then bound to the project: an organization key must belong to the organization hosting it.
A new organization API key starts with mcp:read only. mcp:write satisfies every write tool, so a key that holds it can change workflows, pages and features; for an agent that should do one thing, give the key the narrow scope instead (workflows:write, frames:write, features:write, and so on). Keys created earlier keep the scopes they were given.
The Fabric Kanban API uses separate scopes rather than the MCP umbrella:
kanban:read lists the caller's queue and identity, while kanban:write pulls
and completes the caller's items. Neither scope implies the other. Under your
organization's Settings → API keys, create a key and select Kanban Read
and Kanban Write. A read-only organization role can select only Kanban
Read, so its key cannot pull or complete items. Existing keys without these
scopes need to be replaced from the same settings page before they can use
these routes.
Without valid credentials the gateway answers 401 with
WWW-Authenticate: Bearer resource_metadata="https://your-fabric.com/.well-known/oauth-protected-resource/api/mcp-gateway/projects/<project-id>", scope="mcp:read instructions:read instructions:write offline_access"
(the organization-wide URL names .../oauth-protected-resource/api/mcp-gateway),
which is how an MCP client discovers that it can sign in. A token that is
genuine but was not issued for the URL it was presented at is answered 401 the
same way, with error="invalid_token" added, which sends the client back
through sign-in asking for the right resource. The project metadata's resource
is exactly the project's URL. See
Fabric MCP Gateway for the setup.
MCP Protocol Methods
initialize
Establishes a new MCP session.
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {}
}Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"serverInfo": {
"name": "fabric-mcp-gateway",
"version": "1.0.0"
},
"capabilities": {
"tools": { "listChanged": true }
},
"instructions": "..."
}
}The response includes an Mcp-Session-Id header for subsequent requests.
tools/list
Returns all available tools. A session opened with ?mode=discovery (on
either URL) gets three meta-tools instead, search_tools, get_tool_schema
and call_tool, which find, describe and run the same tools; see
Discovery Mode.
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}Response includes:
- Platform tools (
fabric_*): always present, including the six coding-instruction tools below - Connected server tools (
{prefix}__{tool}): from your MCP server connections
Connected tools include _meta saying whether a call needs runtime authority:
{
"name": "linear__create_issue",
"description": "[Linear] Create a new issue",
"inputSchema": { "..." },
"_meta": {
"requiresAuthority": true,
"providerAuthorityStatus": "missing",
"providerKey": "linear"
}
}requiresAuthority is false for a tool the gateway treats as read-only, which runs
without a grant; such a tool carries no providerAuthorityStatus.
providerAuthorityStatus is granted when the session has any approved grant for the
provider. It is not a promise for that tool, since a grant covers an access level and can
be limited to some tools or to one request.
tools/call
Execute a tool.
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "fabric_list_projects",
"arguments": {
"status": "ACTIVE",
"limit": 10
}
}
}A connected server tool that writes needs active authority; a read-only one runs without it:
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "linear__create_issue",
"arguments": { "project": "ABC", "title": "Example issue" }
}
}If not authorized, returns:
{
"result": {
"content": [{
"type": "text",
"text": "{\"error\":\"Authority required\",\"action\":\"request_authority\",\"providerKey\":\"linear\"}"
}],
"isError": true
}
}Coding Instruction Tools
A project's published coding instructions are served through six platform tools. Each
requires a scope on the credential: a call from a key or sign-in without it is refused with an
error naming the scope, and the codingInstructions field on fabric_list_projects and
fabric_get_project is omitted for a credential that cannot read the instructions.
| Tool | Scope | Kind | Purpose |
|---|---|---|---|
fabric_list_project_instructions | instructions:read | read | Browse or search the published files, or ask what changed since a sinceDigest |
fabric_get_project_instruction | instructions:read | read | Read one published file by path, paged for large files |
fabric_get_project_instruction_bundle | instructions:read | read | Install the whole published tree as one zip |
fabric_instruction_checks | instructions:read | read | Report whether the session is set up the way the instructions expect |
fabric_propose_project_instruction_change | instructions:write | write | Suggest an edit; held for review |
fabric_add_instruction_lesson | instructions:write | write | Record a lesson as a new file under Lessons/; held for review |
instructions:write reaches only the proposal path, which is what a project reader can
already do in the Coding Instructions tab. There is no scope and no argument that publishes
from the gateway: a proposal is approved by a person who can edit the instructions, and on a
project that syncs from a repository it becomes a commit on the proposer's own branch and a
pull request there.
A sign-in grants mcp:read instructions:read instructions:write (the scope in the 401
challenge above). instructions:publish is a separate authority that only an organization
API key created for it carries, and it is not reachable from the gateway.
Living Memory writes
Four tools read and put plain files in the Living Memory folders a project administrator named, without a local clone. Files never reach the repository from the agent: Fabric commits them with the repository integration's own credential.
| Tool | Scope | Kind | Purpose |
|---|---|---|---|
fabric_memory_targets | memory:write | read | List the write folders, their mode and indexMode (INDEXED, or STORE_ONLY for files that stay readable but are left out of AI search, keyword search and summaries), the branch and repository, and the commit the last sync applied |
fabric_memory_read | memory:write | read | List the files under a write folder (prefix, paged by after and limit), or read one file's text (path, paged by offset and maxBytes, default 12,000 and at most 50,000, with nextOffset). Files of a Store only folder are listed and read like any other |
fabric_memory_write | memory:write | write | Write or delete files in one folder as a single commit; a file without ifMatchOid is create-only |
fabric_memory_write_status | memory:write | read | Read a write's receipt: committed, pull request opened, conflict, refused or failed |
memory:write is the one scope that can land a commit without review: on a folder set to
direct push the files are committed to the synced branch, and elsewhere a pull request is
opened and the files are not in Living Memory until a person merges it. A direct push that
loses a race with another write that reached the branch first is retried on the new branch
tip; only a branch that refuses the push (branch protection, a server hook, or missing write
permission) turns the write into a pull request with reason protected. memory:write is never part of
a default sign-in, so a coding tool signed in to the gateway cannot write. The Fabric CLI
asks for it by name when it signs in, the person approves it, and the CLI's session hooks
deliver the files. The three reads also accept mcp:read, since they show only what the
Context tab shows a reader (a coding tool's default sign-in can list and read memory
files but not write them). Coding instructions can never be written this way. Every call
re-checks the person's permission on the project: adding context to write, reading it to
read.
CLI Discovery
Each deployment serves its own build of the Fabric CLI, so a person can run it straight from a URL and the CLI they run is the one written for the server they talk to.
GET https://your-fabric.com/.well-known/fabric-cli.json{
"version": "0.4.0",
"spec": 1,
"integrity": "sha512-…",
"minSupported": "0.4.0",
"nodeRange": ">=22",
"origin": null,
"tarball": "https://your-fabric.com/cli/fabric-0.4.0-0123456789.tgz"
}| Field | Meaning |
|---|---|
version | The CLI version this deployment serves |
spec | The version of this document, currently 1 |
integrity | The tarball's sha512 Subresource Integrity value |
minSupported | The oldest CLI version the deployment accepts |
nodeRange | The Node.js versions the tarball runs on |
origin | The address the tarball was built for, or null when the build did not know it. A CLI with an origin baked in signs in there unless it is given --base-url, which always wins |
tarball | Where to fetch it, on the host that answered; npx -y <tarball> instructions init --tool <tool> runs it with nothing installed (add --base-url <origin> when origin is not the address you are on). The file name ends in ten hex digits of the build's own hash, so a changed build is always at a new URL; an earlier name answers with a 307 to the current one |
Baking an origin in is optional. The build takes it from FABRIC_CLI_ORIGIN, then
NEXT_PUBLIC_SITE_URL, then APP_URL; it never reads what Vercel supplies, because a
preview's address is a per-deployment host and the production domain would be baked into a
staging build. With none set the CLI is still packed, origin is null, and the build says so
in one line. FABRIC_CLI_REQUIRE_ORIGIN=1 makes a missing origin fatal for an operator who
wants the build to refuse. The Connect dialog writes --base-url <the page's address> into its
line unless origin is that address.
The document is public and answered with Cache-Control: public, max-age=60 and an open
CORS header. A deployment built without the pack step answers 404 with
{ "error": "cli_not_served" }, and the Connect dialog then offers only the MCP entries.
Authority Management API
The following oRPC procedures manage authority sessions from the Fabric UI/API:
List Authority Sessions
GET /api/rpc/mcp.authority.listParameters:
| Name | Type | Description |
|---|---|---|
organizationId | string? | Org context (null for personal) |
status | string? | Filter: PENDING, ACTIVE, EXPIRED, REVOKED, COMPLETED |
limit | number? | Max results (default 20) |
offset | number? | Pagination offset |
Get Authority Session
GET /api/rpc/mcp.authority.get| Name | Type | Description |
|---|---|---|
sessionId | string | Authority session ID |
organizationId | string? | Org context |
Approve Authority Session
POST /api/rpc/mcp.authority.approve| Name | Type | Description |
|---|---|---|
sessionId | string | Session to approve |
organizationId | string? | Org context |
instructions | string? | Optional notes for the agent |
Deny Authority Session
POST /api/rpc/mcp.authority.deny| Name | Type | Description |
|---|---|---|
sessionId | string | Session to deny |
organizationId | string? | Org context |
reason | string? | Denial reason |
Revoke Authority Session
POST /api/rpc/mcp.authority.revoke| Name | Type | Description |
|---|---|---|
sessionId | string | Active session to revoke |
organizationId | string? | Org context |
HTTP Methods
| Method | Purpose |
|---|---|
POST /api/mcp-gateway | JSON-RPC requests |
GET /api/mcp-gateway | Server info (no auth) |
DELETE /api/mcp-gateway | Terminate session (include Mcp-Session-Id header) |
POST /api/mcp-gateway/projects/<project-id> | JSON-RPC requests, for one project |
GET /api/mcp-gateway/projects/<project-id> | Server info (no auth) |
DELETE /api/mcp-gateway/projects/<project-id> | Terminate a project session; a session ends only at the URL it was opened at |
Error Codes
| JSON-RPC Code | Meaning |
|---|---|
-32700 | Parse error (malformed JSON) |
-32600 | Invalid JSON-RPC version |
-32601 | Method not found |
-32602 | Missing required parameters, a servers selection the gateway cannot honour (see Choose Which Servers a Client Sees), or a mode other than discovery (see Discovery Mode) |
-32603 | Internal error |
Rate Limits
Standard API rate limits apply. The gateway does not add additional rate limiting beyond what the underlying MCP servers enforce.
Stateless Mode, Durable Execution, and MCP Apps
Stateless Requests
Clients that do not persist Mcp-Session-Id across requests (such as serverless workers, one-shot CLI invocations, or stateless desktop bridges) can send X-Mcp-Stateless: true or append ?stateless=1 to /mcp or /api/mcp-gateway. Each request is authenticated and executed independently without requiring an initialize handshake first.
Idempotent Durable Tool Calls
tools/call requests can opt into Fabric's 24-hour database-backed idempotency store:
- Headers:
X-Mcp-Durable: trueand optionalX-Mcp-Idempotency-Key: <key> - JSON-RPC
_meta:{ "_meta": { "durable": true, "idempotencyKey": "<key>" } } - Tool arguments:
_durable: trueand optional_idempotencyKey: "<key>"
The gateway binds a receipt to the authenticated organization, authenticated user, credential identity, bound or pinned project, selected server or MCP configuration, tool name, key, and a canonical SHA-256 hash of the tool arguments. It claims that receipt before running the tool. Reusing the same key and arguments never runs a completed call again. When the tool's stored result is safe to return, the gateway replays it. Otherwise it returns a non-error completion receipt with the execution ID and completion time, sets _meta.durableExecution.resultWithheld: true, and directs the client to the matching get/list tool for current state without including the stored result. Reusing the key with different arguments is refused, and a live RUNNING call asks the client to retry later. Failed and expired receipts can be reclaimed; a RUNNING receipt becomes stale and reclaimable after 10 minutes.
An organization is required. Without an explicit key the tool still runs, but _meta.durableExecution reports deduplicated: false, stored: false, and reason: "no_idempotency_key"; the gateway does not derive a key. Metadata reports the truthful fabric-idempotency-store (or inline) engine, receipt executionId, status, replay and storage state, and timestamps. If saving the completion receipt fails after the tool succeeds, the gateway returns the tool result and reports that it was not stored.
Interactive MCP Apps (ui://fabric/*)
The gateway advertises the standard resources capability, attaches _meta.ui.resourceUri to supported tools/call results, and serves self-contained text/html;profile=mcp-app views via resources/list and resources/read:
| Resource URI | Companion Tools | Purpose |
|---|---|---|
ui://fabric/project-dashboard | fabric_list_projects, fabric_get_project, fabric_list_frames, fabric_get_frame, fabric_list_workspaces, fabric_get_workspace, fabric_list_artifacts, fabric_get_artifact, fabric_get_identity | Interactive Fabric Projects and Fabric Artifacts & Workspaces cards with 1-click portal and Fabric Desktop launch actions |
ui://fabric/agent-delegation | fabric_list_features (assignedToMe: true), fabric_get_feature, fabric_list_project_pm_assigned_items, fabric_list_tickets, fabric_delegate_agent | Interactive Fabric Tickets & Backlog (Tickets Assigned to You) and Agent Delegation cards with 1-click Start Ticket in Fabric Desktop and Delegate Ticket to Remote Server actions |
ui://fabric/workflow-visualizer | fabric_list_workflows, fabric_get_workflow, fabric_execute_workflow | Visual DAG inspector for workflow results |
ui://fabric/genie-insights | fabric_query_workspace, fabric_search_knowledge, fabric_list_documents, fabric_get_document | Databricks Genie Agents and Lakebase hybrid RAG insight card |
ui://fabric/visualize | fabric_visualize | Declarative A2UI v0.9.1 multi-component canvas (KpiGrid, BarChart, LineChart, DataTable, BadgeList, Timeline) |