Metadata-Version: 2.4
Name: stackless-mcp
Version: 1.0.0b6
Summary: Local MCP server exposing Stackless app APIs to terminal agents
License: Apache-2.0
License-File: LICENSE
Keywords: stackless,mcp,analytics,data,cli
Author: Stackless Data
Author-email: eng@stacklessdata.com
Requires-Python: >=3.11,<4
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Dist: fastmcp (>=2.0,<3.0)
Requires-Dist: httpx (>=0.27.0,<0.28.0)
Requires-Dist: keyring (>=25.7.0,<26.0.0)
Requires-Dist: platformdirs (>=4.0,<5.0)
Requires-Dist: pydantic (>=2.6.1,<3.0.0)
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
Project-URL: Homepage, https://github.com/OxWorks/stackless
Project-URL: Issues, https://github.com/OxWorks/stackless/issues
Project-URL: Repository, https://github.com/OxWorks/stackless
Description-Content-Type: text/markdown

# Stackless MCP

`stackless-mcp` is a local stdio MCP server for Claude Code, Codex, and other
terminal agents. It exposes Stackless app capabilities as MCP tools by calling a
deployed Stackless instance over `/api/v1`.

The MCP process is intentionally thin. It does not import `middleware-service`,
does not need Snowflake or dbt credentials, and does not read local app data.
Stackless remains the source of truth for auth, RBAC, ownership, and mutations.

Use this guide when connecting a terminal agent to your own Stackless instance
from the published `stackless-mcp` package. Development from a monorepo checkout
is covered separately at the end.

## Prerequisite

Install `uv`. The agent configuration uses `uvx`, which is included with `uv`
and fetches the pinned `stackless-mcp` package on first run.

## Install

Pin the beta version exactly in your agent configuration:
`stackless-mcp==<version>`. The MCP server also needs the base URL for your
Stackless instance.

### Codex

Add this block to `~/.codex/config.toml`:

```toml
[mcp_servers.stackless]
command = "uvx"
args = [
  "stackless-mcp==<version>",
  "--base-url",
  "https://your-stackless-instance.example.com",
]
```

### Claude Code

Add this block to `.mcp.json`:

```json
{
  "mcpServers": {
    "stackless": {
      "command": "uvx",
      "args": [
        "stackless-mcp==<version>",
        "--base-url",
        "https://your-stackless-instance.example.com"
      ]
    }
  }
}
```

## Login

Run login once before starting Codex or Claude Code:

```bash
uvx stackless-mcp==<version> login \
  --base-url https://your-stackless-instance.example.com
```

`login` opens the Stackless browser auth flow, receives a local callback from the
authenticated browser session, exchanges it for a scoped `slmcp_` MCP session,
and stores that session locally. The server-side session defaults to a 30-day
TTL. Your Stackless instance can lower that lifetime with
`MCP_SESSION_TTL_SECONDS`.

Credentials are stored in the OS keyring by default. If keyring support is not
available, use file storage:

```bash
uvx stackless-mcp==<version> login \
  --base-url https://your-stackless-instance.example.com \
  --auth-storage file
```

With `--auth-storage file`, credentials are stored as a `0600`
`credentials.json` file in the platform user config directory for
`stackless-mcp`. If you use file storage for login, add
`"--auth-storage", "file"` to the agent configuration too.

## Verify

```bash
uvx stackless-mcp==<version> --version
uvx stackless-mcp==<version> doctor \
  --base-url https://your-stackless-instance.example.com
```

Run `doctor` first when setup does not work. It checks local configuration,
stored auth, Stackless API connectivity, and server capability discovery.

Example successful output:

```json
{
  "auth": {
    "credential_present": true,
    "expires_at": "2026-07-10T12:00:00Z",
    "expiry_status": "unexpired",
    "mode": "stored_token",
    "storage_backend": "keyring",
    "token_present": true,
    "user_id": "user_123"
  },
  "auth_storage": "keyring",
  "base_url": "https://your-stackless-instance.example.com",
  "capabilities": {
    "checked": true,
    "client_known_unsupported_by_server": [],
    "error": null,
    "ok": true,
    "server_supported_unknown_to_client": [],
    "server_version": "2026.06.10"
  },
  "client_version": "<version>",
  "connectivity": {
    "checked": true,
    "ok": true
  },
  "errors": [],
  "ok": true,
  "toolsets": [
    "all"
  ]
}
```

`doctor` exits `0` when required checks pass and exits `1` for local
configuration, auth, or connectivity failures. Missing command arguments and
invalid CLI options exit `2`.

## Troubleshooting

- Missing base URL: pass `--base-url https://...` in the agent config and login
  command, or set `STACKLESS_BASE_URL`.
- Expired or missing token: run `uvx stackless-mcp==<version> login --base-url
  https://your-stackless-instance.example.com` again.
- Server capability delta: `doctor` reports tools known by the client but not
  supported by the server under `client_known_unsupported_by_server`. Upgrade
  the Stackless instance when you need those tools; otherwise the client simply
  advertises the supported subset.
- Connectivity failure: confirm the base URL is reachable from your machine,
  uses the correct scheme, and includes no `/api/v1` suffix.
- Keyring failure: rerun `login` and your agent command with
  `--auth-storage file`.

For a one-shot connectivity check without starting MCP stdio, run:

```bash
uvx stackless-mcp==<version> \
  --base-url https://your-stackless-instance.example.com \
  --check
```

`--check` uses the stored MCP session when present and exits. Expired sessions
prompt a fresh `stackless-mcp login` instead of failing with an opaque MCP
startup error.

## Upgrade

Upgrade by changing the pinned package version in your Codex or Claude Code
configuration, then restart the agent. Pre-release versions follow PEP 440:
beta releases must be pinned exactly. For example, change
`stackless-mcp==<old-version>` to `stackless-mcp==<new-version>` when the new
beta is published.

## Revoke or Reset Auth

```bash
uvx stackless-mcp==<version> logout \
  --base-url https://your-stackless-instance.example.com
uvx stackless-mcp==<version> reset-auth \
  --base-url https://your-stackless-instance.example.com
```

`logout` calls `/mcp/auth/revoke` and then deletes the local credential.
`reset-auth` only deletes the local credential, which is useful for stale or
corrupt local state; the server-side session remains valid until it is revoked
or expires.

To rotate a file-backed credential, run `logout` with `--auth-storage file`,
then run `login --auth-storage file` again. Delete any copied backups of the old
file credential as part of rotation.

## Advanced: Toolsets

This is not part of basic setup. By default, the full supported tool set loads
and the agent decides which tool to call at runtime. Tool selection is automatic
and is not a setup choice.

Use `--toolsets` only when you intentionally want to reduce the loaded
tool-schema surface and agent context:

```toml
[mcp_servers.stackless]
command = "uvx"
args = [
  "stackless-mcp==<version>",
  "--base-url",
  "https://your-stackless-instance.example.com",
  "--toolsets",
  "catalog,runs",
]
```

Valid toolsets are `all`, `core`, `catalog`, `runs`, `transformations`,
`semantic`, `dashboards`, `lifecycle`, and `fivetran`. `all` is the default.
Core tools for auth checks and operation status are always registered; selecting
`core` registers only those tools. Toolsets are a runtime ergonomics feature,
not a security boundary. Stackless backend RBAC and tool permissions still
enforce access.

## Development

Use this path only when developing `stackless-mcp` from a monorepo checkout:

```bash
cd stackless-mcp
poetry install --with dev
poetry run stackless-mcp login \
  --base-url https://your-stackless-instance.example.com
poetry run stackless-mcp \
  --base-url https://your-stackless-instance.example.com
```

Manual token/cookie setup remains for development and compatibility only:

```bash
export STACKLESS_BASE_URL=https://your-stackless-instance.example.com
export STACKLESS_TOKEN='<valid Stackless/Cognito JWT or slmcp token>'
# or, for browser-cookie development auth:
# export STACKLESS_COOKIE='AWSALB=...; AWSELBAuthSessionCookie-0=...'
poetry run stackless-mcp
```

## Tool Surface

Prefer these workflow-style tools for new agents:

| Tool | Description |
| --- | --- |
| `check_stackless_connection` | Check configured Stackless auth/API connectivity. |
| `find_relevant_data` | Find catalog assets relevant to a business question. |
| `explain_stackless_asset` | Explain one catalog asset, columns, and lineage handles. |
| `list_stackless_assets` | List visible catalog assets by type, domain, or tag. |
| `trace_stackless_lineage` | Trace upstream or downstream catalog lineage. |
| `get_stackless_column_details` | Get column metadata for a catalog asset. |
| `refresh_stackless_catalog` | Refresh the catalog snapshot in light or full mode. |
| `get_stackless_connector_status` | Get connector sync status from the catalog snapshot. |
| `get_stackless_asset_freshness` | Summarize upstream freshness for a catalog asset. |
| `list_stackless_snowflake_schemas` | List visible Snowflake schemas from the catalog. |
| `describe_snowflake_object` | Describe a visible Snowflake table or view with typed column metadata. |
| `validate_snowflake_access` | Check RBAC plus Snowflake metadata or zero-row object access. |
| `explain_schema_permissions` | Explain Stackless catalog/RBAC visibility for a Snowflake schema. |
| `query_snowflake` | Run direct read-only Snowflake SQL with Stackless guardrails. |
| `list_fivetran_connector_types` | List Fivetran connector types available for draft creation. |
| `get_fivetran_connector_config_requirements` | Inspect redacted non-secret config requirements for a Fivetran connector type. |
| `list_fivetran_connections` | List group-scoped Fivetran connections with compact operational status. |
| `get_fivetran_connection` | Get current Fivetran connection status and schedule. |
| `get_fivetran_connection_schema` | Read Fivetran schema and table sync configuration. |
| `get_fivetran_health_summary` | Summarize health across configured-group Fivetran connectors. |
| `create_fivetran_connection_draft` | Create a paused non-secret Fivetran connection draft and Connect Card setup link. |
| `reload_fivetran_connection_schema_config` | Reload Fivetran source schema metadata for a connection. |
| `pause_fivetran_connection` | Pause a Fivetran connection after explicit confirmation. |
| `resume_fivetran_connection` | Resume a Fivetran connection after explicit confirmation. |
| `test_fivetran_connection` | Run Fivetran setup tests for a connection. |
| `sync_fivetran_connection` | Trigger an immediate normal Fivetran sync after explicit confirmation. |
| `update_fivetran_connection_schedule` | Change Fivetran connection schedule fields after explicit confirmation. |
| `plan_fivetran_schema_change` | Dry-run exact Fivetran schema/table enable or disable changes. |
| `apply_fivetran_schema_change` | Apply a confirmed Fivetran schema/table enable or disable plan with plan-hash drift rejection. |
| `activate_fivetran_connector_for_agent_access` | Enable synced Fivetran destination schemas for Stackless agent access. |
| `list_stackless_runs` | List recent scheduler runs with stable run refs. |
| `diagnose_stackless_run` | Diagnose one run or job with redacted logs. |
| `get_stackless_run_logs` | Fetch filtered, redacted logs for a scheduler run. |
| `cancel_stackless_run` | Cancel a pending or running scheduler run. |
| `get_transformation_model` | Read a Transformation Model definition, spec, relation, status, version, and ownership. |
| `fork_transformation_model` | Fork a published Transformation Model into a private draft. |
| `update_transformation_model_draft` | Update a private Transformation Model draft and return its readback. |
| `draft_transformation_model` | Scaffold or create a Transformation Model draft. |
| `list_stackless_transformation_models` | List visible Transformation Models. |
| `get_stackless_transformation_model` | Read Transformation Model source-of-truth state from middleware. |
| `validate_transformation_model_draft` | Validate a Transformation Model draft. |
| `preview_transformation_model_draft` | Queue a guarded preview for a Transformation Model draft. |
| `draft_semantic_model` | Scaffold or create a Semantic Model draft. |
| `update_stackless_semantic_model` | Update a Semantic Model, forking published models into an editable draft. |
| `list_stackless_semantic_models` | List visible Semantic Models. |
| `explain_stackless_semantic_model` | Explain a Semantic Model and queryable members. |
| `validate_semantic_model_draft` | Validate a Semantic Model draft or payload. |
| `preview_semantic_model_query` | Run a guarded Semantic Model preview query. |
| `list_stackless_dashboards` | List visible Stackless dashboards. |
| `list_dashboard_export_schedules` | List export schedules for a visible dashboard. |
| `get_dashboard_export_schedule` | Read one dashboard export schedule and monitoring metadata. |
| `list_dashboard_export_schedule_runs` | List export runs for a dashboard export schedule. |
| `list_dashboard_export_eligible_recipients` | List users eligible to receive dashboard export schedules. |
| `create_dashboard_export_schedule` | Create a dashboard export schedule after explicit confirmation. |
| `update_dashboard_export_schedule` | Update a dashboard export schedule after explicit confirmation. |
| `pause_dashboard_export_schedule` | Pause a dashboard export schedule after explicit confirmation. |
| `resume_dashboard_export_schedule` | Resume a dashboard export schedule after explicit confirmation. |
| `unsuspend_dashboard_export_schedule` | Unsuspend a dashboard export schedule after explicit confirmation. |
| `test_send_dashboard_export_schedule` | Trigger a dashboard export test send after explicit confirmation. |
| `delete_dashboard_export_schedule` | Delete a dashboard export schedule after explicit confirmation. |
| `list_dashboard_members` | List Cube members available for custom dashboard widgets. |
| `get_stackless_dashboard` | Get dashboard metadata, custom spec, and workflow hints. |
| `diagnose_stackless_dashboard` | Diagnose custom dashboard widget hydration failures. |
| `describe_gooddata_dashboard` | Describe a visible legacy GoodData dashboard structure and dependencies. |
| `trace_gooddata_dashboard_metrics` | Trace legacy GoodData dashboard visualizations to metrics. |
| `validate_gooddata_filters` | Validate legacy GoodData dashboard filter references against the LDM. |
| `draft_dashboard_from_goal` | Scaffold or create a custom dashboard draft. |
| `clone_stackless_dashboard` | Clone a custom dashboard into an independent private draft. |
| `fork_stackless_dashboard` | Fork a published custom dashboard into a private draft. |
| `edit_stackless_dashboard_section` | Add, remove, or rename one tab/section on a private draft. |
| `edit_stackless_dashboard_section_widget` | Add or remove one widget from a draft tab/section. |
| `patch_stackless_dashboard_layout` | Move or resize selected draft widgets with partial layout patches. |
| `update_stackless_dashboard_draft` | Update a private custom dashboard draft. |
| `hydrate_dashboard` | Hydrate custom dashboard widgets through Stackless/Cube. |
| `validate_dashboard_draft` | Validate a custom dashboard draft or spec. |
| `preview_dashboard` | Hydrate a custom dashboard preview through Stackless/Cube. |
| `diff_stackless_draft` | Inspect draft diff/review output and publish fingerprints before publication. |
| `publish_stackless_draft` | Publish a Stackless draft after confirmation and matching review context. |
| `estimate_stackless_refresh` | Prepare a refresh estimate before refreshing a published resource. |
| `refresh_stackless_resource` | Refresh a published Stackless resource after confirmation. |
| `unpublish_stackless_resource` | Unpublish a Stackless resource after confirmation. |
| `delete_stackless_draft` | Delete a draft resource after confirmation. |
| `get_stackless_operation` | Get status for an MCP operation ID. |
| `get_stackless_invocation` | Recover status for a tool/idempotency key. |

`get_stackless_connector_status` reads the Stackless catalog snapshot. The
`fivetran` toolset calls live Fivetran operational APIs through middleware
workflow handlers and keeps secret config values redacted.

Mutating tools require an `idempotency_key`. Publish, refresh, unpublish,
cancel, delete, guarded Fivetran operations, and dashboard export schedule
mutations also require
`confirmation={"confirmed": true, "evidence": "..."}`.
For dashboard drafts, first call `diff_stackless_draft("dashboard:<id>")`, using
its optional `request` argument for non-default preview filters or table
overrides, and pass the returned `review` object as
`publish_context={"review": review}` to `publish_stackless_draft`. Stackless
rejects stale dashboard fingerprints if the draft changes between review and
publish.
For Semantic Model drafts, first call `diff_stackless_draft("semantic_model:<id>")`
and pass the returned `review` object as `publish_context={"review": review}`.
Use the returned `confirmation_phrase` as confirmation evidence; Stackless
rejects stale semantic-model fingerprints if the draft changes between review
and publish.
For `draft_transformation_model`, an `idempotency_key` is required only when a
`spec` is supplied and a draft is created.

### Managed Transformation Workflow

For managed Transformation Models, use middleware-backed tools for lifecycle
state and catalog-backed tools for discoverability:

1. Create or update a draft with `draft_transformation_model`.
2. Validate and preview it with `validate_transformation_model_draft` and
   `preview_transformation_model_draft`, polling returned operations with
   `get_stackless_operation`.
3. Review the publish diff with `diff_stackless_draft`, then publish with
   `publish_stackless_draft` and explicit confirmation.
4. Verify middleware source-of-truth state with
   `get_stackless_transformation_model`. This is the tool for published version,
   materialization, identity, incremental config, relation metadata, refresh
   policy, and timestamps.
5. Use `explain_stackless_asset` after catalog refresh when you need catalog
   visibility, lineage, columns, or downstream dependency context.
6. Estimate refresh scope first with `estimate_stackless_refresh`. Use the
   returned refresh estimate, fingerprint, confirmation requirement, and
   operation ref before queueing a refresh.
7. Queue the refresh with `refresh_stackless_resource`, passing the estimate
   identifiers, explicit confirmation, and an `idempotency_key`. Poll the
   returned operation ref and use `diagnose_stackless_run` for run details.

Safe Transformation Model fix flow:

1. Call `get_stackless_transformation_model("transformation_model:<published-id>")` or `get_transformation_model("transformation_model:<published-id>")` and inspect the full spec, published relation, status, version, and ownership metadata.
2. Call `fork_transformation_model("transformation_model:<published-id>", idempotency_key="...")` and use the returned `data.draft.refs.draft_ref`.
3. Call `update_transformation_model_draft(draft_ref, idempotency_key="...", spec=..., title=..., description=..., refresh_policy=...)`.
4. Read back with `get_stackless_transformation_model(draft_ref)` or `get_transformation_model(draft_ref)`, then run `validate_transformation_model_draft(draft_ref)` and `preview_transformation_model_draft(draft_ref, idempotency_key="...")`.
5. Call `diff_stackless_draft(draft_ref)` and pass the reviewed publish context to `publish_stackless_draft` with explicit confirmation evidence.

Endpoint-shaped compatibility tools are no longer registered. Use the
workflow-style tools above for all new MCP agent flows.

