---
title: MCP
description: See the tools, operations, and scopes the agent receives.
sidebar:
  order: 2
---

The Model Context Protocol (MCP) lets AI agents and development tools access your Siglata organizations and files. The server uses Streamable HTTP and OAuth 2.0. Permission scopes and membership checks determine what each connection can access.

The product MCP endpoint is:

```text
https://www.siglata.com/v1/mcp
```

## Server identity [#server-identity]

This server publishes distinct identity strings at each layer.

| Layer | String today | Who reads it |
| :-- | :-- | :-- |
| Product / title | `Siglata` (`serverInfo.title`) | MCP clients that show a product title |
| Protocol server name | `siglata` (MCP `initialize` / `serverInfo.name`) | MCP clients during `initialize` |
| Script engine | `CallScript` (`callscript` npm) | Callers of `execute` and `search` |
| Registry package id | `com.siglata/mcp` | MCP registries |
| Plugin / skill key | `siglata` | Agent plugin and skill loaders |

[CallScript](https://www.callscript.dev/) is the engine for `execute` and `search`, not the product brand.

## Capability Surface [#capability-surface]

- **Server name**: `siglata`.
- **Tools**: exactly two, `execute` and `search`.
- **Operations**: Management operations are callable inside `execute` scripts rather than as MCP tools.
- **Org awareness**: Call `principal_get` inside an `execute` script to learn which organization this grant is bound to (`organizationId`), plus `userId`, `role`, and `scopes`. Call `organization_get` for the bound organization's name or slug. Call `organizations_list` to see every organization the authorizing user belongs to; the `current` flag marks the grant-bound org. Listing does not switch the grant — a different workspace needs a new OAuth connection authorized with that org active at consent.
- **Resources**: one template, `siglata:///files/{fileId}`, for grants holding `files:read`. The server exposes no resource list. `subscriptions/listen` on those URIs (up to 64 per stream) emits `notifications/resources/updated` when a watched file's metadata or readability changes; the stream stays bound to grant and session validity.
- **Prompts**: one, `siglata-callscript` — the `search` → `execute` CallScript workflow as a pullable user message.
- **DPoP**: optional. A proof is validated and the token bound to its key when a client presents one, and plain bearer tokens keep working.

## Authorization & Connection Flow [#authorization-flow]

Connecting an MCP client uses an RFC-compliant OAuth 2.0 authorization code flow:

1. **Add Endpoint**: Configure your client with the server URL `https://www.siglata.com/v1/mcp`.
2. **Initiate OAuth**: Your client opens a browser window targeting Siglata's authorization endpoint.
3. **Authenticate**: Sign in via your email magic link if not already authenticated.
4. **Select Organization**: Choose the specific organization this connection will access. Every grant is strictly bound to a single organization ID.
5. **Approve Scopes**: Review the requested capability scopes (e.g., `files:read`, `files:write`, `organizations:read`) and authorize access.
6. **Token Delivery**: The client receives an access token scoped exclusively to the chosen organization.

```
┌────────────────┐        1. OAuth Flow        ┌──────────────────┐
│   MCP Client   │ ──────────────────────────> │  Siglata Auth    │
│ (Claude/Cursor)│ <────────────────────────── │  (Siglata Auth)  │
└────────────────┘       2. Scoped Token       └──────────────────┘
        │
        │ 3. JSON-RPC (POST /v1/mcp)
        ▼
┌─────────────────────────────────────────────────────────────────┐
│                     Siglata MCP Server                          │
│  - Origin Verification & Session Validation                     │
│  - Dynamic Membership & Scope Policy Check                      │
│  - Organization Boundary Isolation                              │
└─────────────────────────────────────────────────────────────────┘
        │                                 │
        ▼                                 ▼
┌──────────────────┐              ┌──────────────────┐
│ File Operations  │              │  Org & Members   │
│ (8 MiB chunks)   │              │ (RBAC / Invites) │
└──────────────────┘              └──────────────────┘
```

## CLI device authorization [#cli-device-authorization]

Headless CLIs that cannot complete a browser redirect use the OAuth 2.0 device authorization grant (`urn:ietf:params:oauth:grant-type:device_code`). Register a public client (`token_endpoint_auth_method: none`) whose `grant_types` include that device grant (and `refresh_token` if you need refresh). Discovery advertises `device_authorization_endpoint`.

1. `POST /auth/device/code` with `client_id`, `scope`, and `resource` set to `https://www.siglata.com/v1/mcp`.
2. Open `verification_uri` (or `verification_uri_complete`) in a browser — Siglata serves `/app/device`. Sign in, select an organization if needed, and approve.
3. Poll `POST /auth/oauth2/token` with `grant_type=urn:ietf:params:oauth:grant-type:device_code` until the access token arrives. Do **not** poll `/auth/device/token` for MCP; that endpoint is not the MCP OAuth token path.

The issued JWT has `aud` = the MCP resource and `organizationId` frozen to the organization active when the user approved. Changing the active organization later does not rebind an existing device grant — authorize again for a different workspace.

Authorization-code IDE clients keep using `/oauth2/authorize` → `/app/consent` unchanged.

## OAuth Scopes [#oauth-scopes]

Siglata enforces principle-of-least-privilege capability scopes:

| Scope | Description | Minimum Role |
| :-- | :-- | :-- |
| `files:read` | Inspect active files, list trash, inspect storage metrics, and obtain authenticated download URLs. | `member` |
| `files:write` | Reserve uploads, complete transfers, cancel uploads, rename files, trash, and restore files. | `member` |
| `organizations:read` | Read organization profile and metadata for the granted workspace. | `member` |
| `organizations:write` | Update organization name or slug, or create new organizations. | `admin` |
| `members:read` | List organization members and view pending invitations. | `member` |
| `members:write` | Invite new members, cancel pending invitations, update roles, or remove members. | `admin` |

In addition to OAuth scopes, Siglata evaluates your active organization membership in real time on every operation. If a user's role changes or membership is revoked, access is immediately blocked. Product MCP also requires a per-organization access tier (`testing` or `upgraded`); organizations with `revoked` status (missing rows auto-ensure `testing`) fail with `MCP_ACCESS_REVOKED`.

## Tools & Operations Reference [#tools-reference]

`tools/list` advertises exactly two tools, backed by [CallScript](https://www.callscript.dev/):

- **`execute`** runs a script that batches management operations into one round trip. Calls run server-side and compose: a script can list files, then rename or move each result, and only the returned value crosses the wire.
- **`search`** lists the operation signatures this grant may call, so a client discovers its callable set without probing.

```js title="An execute script batching two operations"
const trash = await files_list({ state: "trash" });
const storage = await storage_get({});
return { trash, storage };
```

The operations below are functions inside `execute` scripts — calling one directly by name through `tools/call` returns a JSON-RPC error with `error.code` `-32602` and `error.data.code` `USE_EXECUTE`, redirecting the caller to `execute`. An operation whose required scope or member role is missing is never mounted for the grant: `search` does not list it and a script naming it fails validation. `search` cards declare each operation's failure codes, and scripts containing `suspend` steps are rejected as `invalid` — write single-pass scripts.

Call `search` for the signature card of every operation this grant may call — parameters, return shapes, and declared failure codes — filtered to the grant's scopes and role.

### Files

| Operation | Purpose |
| :-- | :-- |
| `files_list` | Lists active files or recoverable trash in the organization. |
| `uploads_list` | Lists unfinished upload reservations so they can be resumed or cancelled. |
| `storage_get` | Retrieves the organization's current storage metrics in bytes. |
| `file_get` | Reads one file's metadata and lifecycle state. |
| `folder_get` | Reads one folder's metadata and lifecycle state. |
| `file_read` | Reads a file's bytes inline, or returns authenticated transfer instructions for larger files. |
| `sheet_list` | Lists worksheets in a stored `.xlsx` without returning workbook bytes. |
| `sheet_read` | Reads an A1 cell range from a stored `.xlsx` as JSON cells without returning workbook bytes. |
| `sheet_write` | Patches one or more A1 ranges (`patches[]`) on an existing workbook, preserves cells outside those ranges and untouched sheets, and returns a new edition file id without returning workbook bytes. |
| `relation_extract` | Extracts named relation tables from stored `.xlsx` workbooks, one outcome per requested section; `persist` stores each extracted section for later queries. |
| `relation_query` | Queries a persisted relation on a stored `.xlsx` with filters, ordering, and pagination, without reopening the workbook. |
| `doc_list` | Counts body paragraphs in a stored `.docx` without returning document bytes. |
| `doc_read` | Reads plain paragraph text from a stored `.docx` without returning document bytes. |
| `pdf_list` | Counts pages in a stored PDF without returning document bytes. |
| `pdf_read` | Reads plain page text from a stored PDF without returning document bytes. |
| `ppt_list` | Lists slide indexes and title placeholders in a stored `.pptx` without returning archive bytes. |
| `ppt_read` | Reads plain slide paragraph text and speaker `notes` from a stored `.pptx` without returning archive bytes. |
| `file_download` | Obtains authenticated HTTP download instructions for a file. |
| `file_write` | Creates a small file inline. |
| `file_rename` | Renames a file without modifying or re-uploading its stored bytes. |
| `file_set_visibility` | Sets a file's visibility to org-wide or restricted. |
| `file_move` | Moves a file into a folder or back to the organization root. |
| `file_copy` | Copies an active file into a folder or the organization root, charging storage quota for the full size. |
| `file_trash` | Moves an active file to recoverable trash. |
| `file_restore` | Restores a trashed file to active state. |
| `file_purge` | Permanently deletes a trashed file and releases its storage quota. |
| `upload_begin` | Reserves storage quota and initiates a multipart upload session. |
| `upload_complete` | Finalizes an upload after all parts have been transferred. |
| `upload_cancel` | Cancels an unfinished upload and frees its quota reservation. |

### Folders & Access

| Operation | Purpose |
| :-- | :-- |
| `folders_list` | Lists folders in the organization. |
| `folder_create` | Creates a folder, optionally nested under a parent folder. |
| `folder_rename` | Renames a folder without affecting its contents. |
| `folder_set_visibility` | Sets a folder's visibility to org-wide or restricted. |
| `folder_move` | Moves a folder under a new parent or back to the organization root. |
| `folder_copy` | Deep-copies an active folder tree and returns the new root folder only. |
| `folder_trash` | Moves a folder to recoverable trash. |
| `folder_restore` | Restores a trashed folder before its recovery deadline. |
| `folder_purge` | Permanently deletes a trashed folder. |
| `grants_list` | Lists the explicit access grants on a file or folder. |
| `grant_create` | Grants a member read or write access to a file or folder. |
| `grant_revoke` | Revokes an access grant. |

### Organization & Team

| Operation | Purpose |
| :-- | :-- |
| `principal_get` | Reads the identity, role, and scopes bound to this grant. |
| `organization_get` | Retrieves details for the selected organization. |
| `organizations_list` | Lists organizations the authorizing user belongs to; `current` marks the grant-bound org without switching it. |
| `organization_update` | Updates the name or slug of the selected organization. |
| `organization_create` | Creates a new organization. |
| `organization_delete` | Permanently deletes the selected organization and its files. Owner only. |
| `members_list` | Lists team members in the organization with pagination. |
| `member_update_role` | Changes a team member's role. |
| `member_remove` | Removes a member from the organization. |
| `invitation_create` | Invites a new member to the organization via email. |
| `invitation_resend` | Resends a pending invitation email for the selected organization. |
| `invitations_list` | Lists all pending invitations for the organization. |
| `invitation_cancel` | Revokes an unaccepted invitation. |
| `invitations_mine` | Lists pending invitations addressed to the authorizing user (may include other organizations). |
| `invitation_accept` | Accepts a pending invitation for the grant-bound organization only. Does not rebind the OAuth grant; accepting another organization requires console accept and a new grant. |
| `invitation_reject` | Rejects a pending invitation for the grant-bound organization only. Does not rebind the OAuth grant. |
| `organization_leave` | Leaves the grant-bound organization. The next MCP call fails membership. |
| `sessions_list` | Lists this principal's own live MCP grant sessions. |
| `session_revoke` | Revokes one of your own MCP grant sessions. |

## Resources [#resources]

Grants holding `files:read` also see one resource template, `siglata:///files/{fileId}`, which resolves a file's bytes through `resources/read`. Textual media returns decoded text and other media returns base64 for files up to 1 MiB; larger files resolve to the same authenticated transfer instructions as `file_read`. The grant is re-checked on every read.

### Watching files [#watching-files]

`subscriptions/listen` on `siglata:///files/{fileId}` URIs opens a server-sent stream that emits `notifications/resources/updated` when a watched file changes. The stream honors up to 64 URIs; URIs outside the template, or any subscription on a grant without `files:read`, are rejected before the stream opens.

The first observation of each URI is a baseline and never emits. After that, one notification is emitted when a file's metadata changes, when it becomes unreadable to this grant (deleted, restricted, or its grant revoked), and when it becomes readable again. Identical or repeatedly-unreadable states stay silent — a notification means "re-read the resource," never a diff of contents.

Each watched URI is re-authorized on every evaluation under the grant that opened the stream: a file you can no longer read is indistinguishable from one that does not exist. File mutations push a best-effort hint to the watch hub for low latency; a periodic sweep re-checks every watcher so a dropped hint still surfaces. The stream ends when the client disconnects, when the grant stops resolving (revoked session, dropped membership), or at the earlier of the grant's expiry and one hour — clients re-listen to continue watching.

## Install [#install]

Connect over OAuth to `https://www.siglata.com/v1/mcp`. Client install steps live on dedicated pages (copy-paste commands for people and agents). Start at [Connect](/docs/en-US/agents/connect).

- Proven (v1): [Cursor](/docs/en-US/agents/install/cursor), [Codex](/docs/en-US/agents/install/codex)
- Installable / spec-compatible: [ChatGPT Desktop](/docs/en-US/agents/install/chatgpt-desktop), [Claude Desktop](/docs/en-US/agents/install/claude-desktop), [VS Code](/docs/en-US/agents/install/vs-code)

This page documents the MCP surface only (`execute`, `search`, CallScript operations, resources, scopes). It does not duplicate those install guides.

## Security & Revocation [#security]

- **Strict Multi-Tenancy**: An MCP grant grants access to exactly one organization. To access another workspace, authenticate an additional connection.
- **Active State Validation**: Tokens are verified against database session records and active organization membership on each request.
- **Revocation**: A grant stops working when its authorizing session ends or the member leaves the organization. Drop a connection in-band with `session_revoke`, revoke the session through `POST /auth/revoke-session`, or remove the member with `member_remove`; either way, the client's next request is rejected.

## Changing scopes after authorization [#changing-scopes]

Scopes are chosen at consent and stored on the grant. There is no post-grant scope mutation API (`scopes_update` or similar), because widening scopes without reconsent would bypass the consent trust boundary. To change scopes, revoke the current grant with `session_revoke` (or revoke the session / leave the organization), then run OAuth again and approve the desired scope set at consent.

## MCP Registry [#mcp-registry]

The server is listed on the official MCP Registry as [com.siglata/mcp](https://registry.modelcontextprotocol.io/v0.1/servers/com.siglata%2Fmcp/versions/latest).
