stacklet-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. stacklet_mcp-0.1.0/.github/CODEOWNERS +1 -0
  2. stacklet_mcp-0.1.0/.github/composites/install/action.yml +31 -0
  3. stacklet_mcp-0.1.0/.github/dependabot.yaml +6 -0
  4. stacklet_mcp-0.1.0/.github/workflows/ci.yml +35 -0
  5. stacklet_mcp-0.1.0/.github/workflows/release.yml +26 -0
  6. stacklet_mcp-0.1.0/.gitignore +21 -0
  7. stacklet_mcp-0.1.0/.pre-commit-config.yaml +41 -0
  8. stacklet_mcp-0.1.0/.tool-versions +3 -0
  9. stacklet_mcp-0.1.0/CHANGELOG.md +6 -0
  10. stacklet_mcp-0.1.0/CLAUDE.md +207 -0
  11. stacklet_mcp-0.1.0/PKG-INFO +13 -0
  12. stacklet_mcp-0.1.0/README.md +115 -0
  13. stacklet_mcp-0.1.0/justfile +42 -0
  14. stacklet_mcp-0.1.0/license-header.tpl +1 -0
  15. stacklet_mcp-0.1.0/pyproject.toml +74 -0
  16. stacklet_mcp-0.1.0/stacklet/mcp/__init__.py +8 -0
  17. stacklet_mcp-0.1.0/stacklet/mcp/__main__.py +11 -0
  18. stacklet_mcp-0.1.0/stacklet/mcp/assetdb/__init__.py +4 -0
  19. stacklet_mcp-0.1.0/stacklet/mcp/assetdb/models.py +268 -0
  20. stacklet_mcp-0.1.0/stacklet/mcp/assetdb/redash.py +268 -0
  21. stacklet_mcp-0.1.0/stacklet/mcp/assetdb/sql_info.md +147 -0
  22. stacklet_mcp-0.1.0/stacklet/mcp/assetdb/tools.py +404 -0
  23. stacklet_mcp-0.1.0/stacklet/mcp/cmdline.py +67 -0
  24. stacklet_mcp-0.1.0/stacklet/mcp/docs/__init__.py +4 -0
  25. stacklet_mcp-0.1.0/stacklet/mcp/docs/client.py +80 -0
  26. stacklet_mcp-0.1.0/stacklet/mcp/docs/models.py +33 -0
  27. stacklet_mcp-0.1.0/stacklet/mcp/docs/tools.py +71 -0
  28. stacklet_mcp-0.1.0/stacklet/mcp/lifespan.py +52 -0
  29. stacklet_mcp-0.1.0/stacklet/mcp/mcp.py +23 -0
  30. stacklet_mcp-0.1.0/stacklet/mcp/mcp_info.md +40 -0
  31. stacklet_mcp-0.1.0/stacklet/mcp/platform/__init__.py +4 -0
  32. stacklet_mcp-0.1.0/stacklet/mcp/platform/dataset_info.md +115 -0
  33. stacklet_mcp-0.1.0/stacklet/mcp/platform/graphql.py +250 -0
  34. stacklet_mcp-0.1.0/stacklet/mcp/platform/graphql_info.md +71 -0
  35. stacklet_mcp-0.1.0/stacklet/mcp/platform/models.py +152 -0
  36. stacklet_mcp-0.1.0/stacklet/mcp/platform/tools.py +240 -0
  37. stacklet_mcp-0.1.0/stacklet/mcp/server.py +35 -0
  38. stacklet_mcp-0.1.0/stacklet/mcp/settings.py +42 -0
  39. stacklet_mcp-0.1.0/stacklet/mcp/stacklet_auth.py +105 -0
  40. stacklet_mcp-0.1.0/stacklet/mcp/utils/__init__.py +4 -0
  41. stacklet_mcp-0.1.0/stacklet/mcp/utils/file.py +31 -0
  42. stacklet_mcp-0.1.0/stacklet/mcp/utils/json.py +67 -0
  43. stacklet_mcp-0.1.0/stacklet/mcp/utils/mcp_json.py +82 -0
  44. stacklet_mcp-0.1.0/stacklet/mcp/utils/text.py +14 -0
  45. stacklet_mcp-0.1.0/stacklet/mcp/utils/tool.py +27 -0
  46. stacklet_mcp-0.1.0/tests/__init__.py +6 -0
  47. stacklet_mcp-0.1.0/tests/conftest.py +64 -0
  48. stacklet_mcp-0.1.0/tests/factory.py +146 -0
  49. stacklet_mcp-0.1.0/tests/test_cmdline.py +61 -0
  50. stacklet_mcp-0.1.0/tests/test_settings.py +122 -0
  51. stacklet_mcp-0.1.0/tests/test_stacklet_auth.py +179 -0
  52. stacklet_mcp-0.1.0/tests/test_tools_assetdb.py +685 -0
  53. stacklet_mcp-0.1.0/tests/test_tools_docs.py +100 -0
  54. stacklet_mcp-0.1.0/tests/test_tools_platform.py +674 -0
  55. stacklet_mcp-0.1.0/tests/test_utils_mcp_json.py +49 -0
  56. stacklet_mcp-0.1.0/tests/test_utils_text.py +18 -0
  57. stacklet_mcp-0.1.0/tests/testing/http.py +140 -0
  58. stacklet_mcp-0.1.0/tests/testing/mcp.py +76 -0
  59. stacklet_mcp-0.1.0/tests/testing/settings.py +33 -0
  60. stacklet_mcp-0.1.0/uv.lock +1380 -0
@@ -0,0 +1 @@
1
+ * @stacklet/engineering
@@ -0,0 +1,31 @@
1
+ name: Common setup
2
+ description: common setup for actions
3
+ runs:
4
+ using: composite
5
+ steps:
6
+ - name: Tool versions
7
+ uses: wistia/parse-tool-versions@v2.1.1
8
+ with:
9
+ prefix: TOOL_VERSION_
10
+
11
+ - name: Setup Just
12
+ uses: extractions/setup-just@v3
13
+ with:
14
+ just-version: ${{ env.TOOL_VERSION_JUST }}
15
+
16
+ - name: Setup Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ env.TOOL_VERSION_PYTHON }}
20
+
21
+ - name: Setup uv
22
+ uses: astral-sh/setup-uv@v6
23
+ with:
24
+ version: ${{ env.TOOL_VERSION_UV }}
25
+ activate-environment: true
26
+ enable-cache: true
27
+
28
+ - name: Install dependencies
29
+ shell: sh
30
+ run: |
31
+ just install
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
@@ -0,0 +1,35 @@
1
+ name: "CI"
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - release/**
8
+ pull_request:
9
+
10
+ jobs:
11
+ lint:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout
15
+ uses: actions/checkout@v5
16
+
17
+ - name: Install
18
+ uses: ./.github/composites/install
19
+
20
+ - name: Lint
21
+ run: |
22
+ just lint
23
+
24
+ test:
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - name: Checkout
28
+ uses: actions/checkout@v5
29
+
30
+ - name: Install
31
+ uses: ./.github/composites/install
32
+
33
+ - name: Unit tests
34
+ run: |
35
+ just test-coverage
@@ -0,0 +1,26 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v[0-9]+.[0-9]+.[0-9]+"
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ id-token: write
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v5
17
+
18
+ - name: Install
19
+ uses: ./.github/composites/install
20
+
21
+ - name: Build packages
22
+ run: |
23
+ uv build
24
+
25
+ - name: Publish packges to PyPI
26
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,21 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ .coverage
7
+ .coverage.*
8
+ .pytest_cache/
9
+
10
+ # IDE
11
+ .vscode/*
12
+ !.vscode/settings.json
13
+ !.vscode/launch.json
14
+ *.swp
15
+ *.swo
16
+
17
+ # OS
18
+ .DS_Store
19
+
20
+ # Local config
21
+ .mcp.json
@@ -0,0 +1,41 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v6.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: debug-statements
8
+
9
+ - repo: https://github.com/astral-sh/ruff-pre-commit
10
+ rev: v0.12.7
11
+ hooks:
12
+ - id: ruff-check
13
+ args: [--fix]
14
+ - id: ruff-format
15
+
16
+ - repo: https://github.com/tox-dev/pyproject-fmt
17
+ rev: v2.6.0
18
+ hooks:
19
+ - id: pyproject-fmt
20
+
21
+ - repo: https://github.com/pre-commit/mirrors-mypy
22
+ rev: v1.13.0
23
+ hooks:
24
+ - id: mypy
25
+ args: [--config-file=pyproject.toml]
26
+ exclude: ^tests/
27
+ # some dependencies don't export types, so they're needed in the mypy
28
+ # virtualenv
29
+ additional_dependencies:
30
+ - fastmcp
31
+ - pydantic
32
+
33
+ - repo: https://github.com/arkinmodi/add-license-header
34
+ rev: v2.4.0
35
+ hooks:
36
+ - id: add-license-header
37
+ args:
38
+ - --single-year-if-same
39
+ - --year-delimiter='-'
40
+ - --license-file=license-header.tpl
41
+ files: ^.*\.py$
@@ -0,0 +1,3 @@
1
+ just 1.40.0
2
+ uv 0.8.14
3
+ python 3.12.10
@@ -0,0 +1,6 @@
1
+ ## 0.1.0 - 2025-09-23
2
+
3
+ - First release
4
+ - Provide AssetDB tools for managing and running SQL queries (both saved and ad-hoc)
5
+ - Provide Platform tools for interacting with the GraphQL API
6
+ - Provide tools for accessing the official documentation
@@ -0,0 +1,207 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is an MCP (Model Context Protocol) server that provides comprehensive tools for interacting with the Stacklet platform. The server exposes tools for documentation access, Stacklet's cloud governance GraphQL API, and AssetDB operations (with some tools conditionally enabled based on configuration).
8
+
9
+ ## Architecture
10
+
11
+ The codebase follows a modular design with clear separation of concerns:
12
+
13
+ **Core Components:**
14
+ - `stacklet/mcp/server.py` - Server factory that creates the FastMCP instance
15
+ - `stacklet/mcp/mcp.py` - Main entry point with CLI integration
16
+ - `stacklet/mcp/cmdline.py` - Command line interface with agent config generation
17
+ - `stacklet/mcp/stacklet_auth.py` - Authentication credential loading
18
+ - `stacklet/mcp/utils/` - Utility functions package (text, json, mcp_json, tool helpers)
19
+ - `stacklet/mcp/settings.py` - Server configuration and feature flags
20
+ - `stacklet/mcp/lifespan.py` - Application lifespan management
21
+
22
+ **Docs Package:**
23
+ - `stacklet/mcp/docs/client.py` - Documentation client for fetching docs from Stacklet deployment
24
+ - `stacklet/mcp/docs/tools.py` - Documentation tool implementations (docs_list, docs_read)
25
+ - `stacklet/mcp/docs/models.py` - Pydantic models for documentation responses
26
+
27
+ **Platform Package:**
28
+ - `stacklet/mcp/platform/graphql.py` - Platform GraphQL client with instance-level schema caching
29
+ - `stacklet/mcp/platform/tools.py` - Platform tool implementations (platform_graphql_info, platform_graphql_query, platform_dataset_export, etc.)
30
+ - `stacklet/mcp/platform/models.py` - Pydantic models for platform operations (ExportColumn, ExportParam, ConnectionExport, etc.)
31
+ - `stacklet/mcp/platform/graphql_info.md` - Detailed guidance for using the Platform GraphQL API
32
+ - `stacklet/mcp/platform/dataset_info.md` - Guide for exporting large datasets from the Platform API
33
+
34
+ **AssetDB Package:**
35
+ - `stacklet/mcp/assetdb/redash.py` - AssetDB client using Redash API for SQL queries and saved query management
36
+ - `stacklet/mcp/assetdb/models.py` - Pydantic models specific to AssetDB (Query, User, JobStatus, QueryUpsert, etc.)
37
+ - `stacklet/mcp/assetdb/tools.py` - AssetDB tool implementations (assetdb_query_list, assetdb_sql_query, etc.)
38
+ - `stacklet/mcp/assetdb/sql_info.md` - Comprehensive guide to AssetDB structure and querying best practices
39
+
40
+ **Authentication Flow:**
41
+ The authentication system echoes the Stacklet Terraform provider's credential resolution:
42
+ 1. Environment variables (`STACKLET_ENDPOINT`, `STACKLET_ACCESS_TOKEN`, `STACKLET_IDENTITY_TOKEN`)
43
+ 2. Config files saved by the `stacklet-admin` CLI in `~/.stacklet`
44
+
45
+ Note: `identity_token` is required for AssetDB access via Redash authentication cookies.
46
+
47
+ **Tool Naming Convention:**
48
+ Tools use component-based prefixes:
49
+ - `platform_*` - Tools for Stacklet's platform GraphQL API
50
+ - `assetdb_*` - Tools for asset database operations (SQL queries and saved query management)
51
+ - Pattern: `{component}_{action}` (e.g., `platform_graphql_query`, `assetdb_sql_query`)
52
+
53
+ ## Development Commands
54
+
55
+ **Install dependencies:**
56
+ ```bash
57
+ uv sync
58
+ # or: just install
59
+ ```
60
+
61
+ **Run the MCP server:**
62
+ ```bash
63
+ uv run stacklet-mcp
64
+ # or: just run
65
+ ```
66
+
67
+ **Development commands (via justfile):**
68
+ ```bash
69
+ just install # Install dependencies and generate .mcp.json if needed
70
+ just lint # Run pre-commit hooks (formatters and linters)
71
+ just test # Run pytest with optional args
72
+ just test-coverage # Run tests with coverage reporting
73
+ just inspect # Run MCP inspector tool
74
+ just agent-config # Generate .mcp.json configuration
75
+ ```
76
+
77
+
78
+ ## MCP Tools Available
79
+
80
+ **Documentation Tools:**
81
+ 1. **`docs_list`** - List all available Stacklet user documentation files
82
+ 2. **`docs_read`** - Read a specific Stacklet documentation file
83
+
84
+ **Platform GraphQL Tools:**
85
+ 3. **`platform_graphql_info`** - Key information for LLMs using GraphQL tools (call this first)
86
+ 4. **`platform_graphql_list_types`** - List the types available in the GraphQL API
87
+ 5. **`platform_graphql_get_types`** - Retrieve information about specific GraphQL types
88
+ 6. **`platform_graphql_query`** - Execute GraphQL queries against Stacklet platform
89
+ 7. **`platform_dataset_info`** - Guide for exporting large datasets
90
+ 8. **`platform_dataset_export`** - Export full datasets from GraphQL connections to CSV format
91
+ 9. **`platform_dataset_lookup`** - Check the status of dataset exports
92
+
93
+ **AssetDB Tools:**
94
+ 10. **`assetdb_sql_info`** - Key information for LLMs using AssetDB SQL tools (call this first)
95
+ 11. **`assetdb_sql_query`** - Execute ad-hoc SQL queries against AssetDB
96
+ 12. **`assetdb_query_list`** - List and search saved queries with pagination
97
+ 13. **`assetdb_query_get`** - Get detailed information about specific saved queries
98
+ 14. **`assetdb_query_result`** - Get results for saved queries with caching control
99
+ 15. **`assetdb_query_save`** - Create new queries or update existing ones (conditionally enabled via `STACKLET_MCP_ASSETDB_ALLOW_SAVE=true`)
100
+ 16. **`assetdb_query_archive`** - Archive saved queries (conditionally enabled via `STACKLET_MCP_ASSETDB_ALLOW_ARCHIVE=true`)
101
+
102
+ Total: 16 tools (2 docs + 7 platform + 7 assetdb tools, with 2 assetdb tools conditionally enabled)
103
+
104
+ The actual tools available are determined by each package's `tools()` function implementation, with some tools conditionally enabled based on server configuration settings.
105
+
106
+ ## Key Implementation Details
107
+
108
+ **Schema Caching:** The `PlatformClient` class implements instance-level caching to avoid repeated introspection queries, improving performance for schema-heavy operations.
109
+
110
+ **Client Management:** Both AssetDB and Platform clients use a `.get(ctx)` pattern for lazy initialization and caching in FastMCP context. Credentials are loaded once per session using `StackletCredentials.get(ctx)`.
111
+
112
+ **Error Handling:** All GraphQL and SQL operations return structured responses, with network errors and JSON parsing errors handled gracefully. AssetDB supports async query polling for long-running operations.
113
+
114
+ **Credential Security:** Access tokens and identity tokens are never logged or exposed in error messages.
115
+
116
+ **Platform Integration:** Uses GraphQL API for Stacklet platform operations. The Platform package is organized into:
117
+ - `graphql.py` - Core GraphQL client with schema caching and introspection
118
+ - `tools.py` - FastMCP tool implementations that expose platform functionality (info, list types, get types, query, dataset exports)
119
+ - `models.py` - Pydantic models for exports and GraphQL operations
120
+ Uses `graphql-core` for schema manipulation and SDL generation, enabling proper type introspection and schema documentation.
121
+
122
+ **AssetDB Integration:** Uses Redash API for SQL query execution and saved query management. The AssetDB package is organized into:
123
+ - `redash.py` - Core client with async operations and authentication
124
+ - `models.py` - Pydantic models for Redash API responses (Query, User, JobStatus, etc.)
125
+ - `tools.py` - FastMCP tool implementations that expose AssetDB functionality
126
+ Supports query timeouts (max 300s), pagination, search, and tag filtering.
127
+
128
+ ## Configuration
129
+
130
+ **Stacklet Credentials:**
131
+ The server requires Stacklet credentials configured through one of:
132
+ - Environment variables: `STACKLET_ENDPOINT`, `STACKLET_ACCESS_TOKEN`, and `STACKLET_IDENTITY_TOKEN`
133
+ - CLI config: `~/.stacklet/config.json` (endpoint), `~/.stacklet/credentials` (access token), and `~/.stacklet/id` (identity token)
134
+
135
+ **Server Settings:**
136
+ Additional configuration via environment variables with `STACKLET_MCP_` prefix:
137
+ - `STACKLET_MCP_DOWNLOADS_PATH` (default: system temp directory) - Directory for storing query result files
138
+ - `STACKLET_MCP_ASSETDB_DATASOURCE` (default: 1) - AssetDB data source ID
139
+ - `STACKLET_MCP_ASSETDB_ALLOW_SAVE` (default: false) - Enable query save/update functionality
140
+ - `STACKLET_MCP_ASSETDB_ALLOW_ARCHIVE` (default: false) - Enable query archiving functionality
141
+ - `STACKLET_MCP_PLATFORM_ALLOW_MUTATIONS` (default: false) - Enable calling mutations in the Platform GraphQL API
142
+
143
+ **File Storage:**
144
+ Query results from AssetDB tools are automatically saved to the configured downloads directory:
145
+ - Complete query results are saved as JSON files for analysis with other tools
146
+ - Files use descriptive naming: `assetdb_{query_id}_{result_id}.json` (for saved queries) or `assetdb_{result_id}.json` (for ad-hoc queries)
147
+ - The downloads directory is created automatically if it doesn't exist
148
+ - Files persist after tool execution for further analysis
149
+
150
+ **External Dependencies:**
151
+ - Documentation files are fetched from the live Stacklet docs service at runtime
152
+ - Redash endpoint is derived by replacing "api." with "redash." in the platform endpoint
153
+ - Docs endpoint is derived by replacing "api." with "docs." in the platform endpoint
154
+
155
+ ## Known Issues & Design Notes
156
+
157
+ When you're editing code which matches one of these concerns, think extra hard about
158
+ the impact of your changes; prefer to mitigate these issues rather than further
159
+ entrench them.
160
+
161
+ **Documentation Service Dependency:** The docs client fetches documentation from a live Stacklet deployment's docs service (derived by replacing "api." with "docs." in the platform endpoint). This requires proper authentication and network access to the docs service.
162
+
163
+ **AssetDB Data Source:** The AssetDB client defaults to `data_source_id=1` for the main AssetDB instance. This is hardcoded but can be overridden in function calls
164
+ internally.
165
+
166
+ **Authentication Complexity:** Requires three different credential fields (endpoint, access_token, identity_token) which must all be configured correctly for full functionality.
167
+
168
+ **Test Coverage:** Most tests are end-to-end tool tests with mocked downstream HTTP
169
+ interactions, which is an appropriate level of abstraction for most cases in this codebase. AssetDB in particular is lacking test coverage in some areas, but most tools are well tested, and the patterns seen in the existing tests should be repeated where possible.
170
+
171
+ **Dict Returns:** Many tools and client methods should return better-structured data.
172
+
173
+ **Loose Validation:** Tool parameters in particular could often benefit from further
174
+ type annotation to encode (and advertise to clients!) expectations. Obvious examples include:
175
+ - download_format literals
176
+ - assetdb result timeout
177
+ - query_id >= 1
178
+
179
+ ## Agent Configuration
180
+
181
+ **MCP Client Configuration:**
182
+ The server supports generating `.mcp.json` configuration files for Claude Desktop and other MCP clients:
183
+
184
+ ```bash
185
+ # List available profiles
186
+ just run agent-config list
187
+
188
+ # Generate configuration for default profile (restricted)
189
+ just run agent-config generate default
190
+
191
+ # Generate configuration for unrestricted profile (all tools enabled)
192
+ just run agent-config generate unrestricted
193
+ ```
194
+
195
+ **Configuration Profiles:**
196
+ - `default` - Safe profile with write operations disabled (assetdb_allow_save=false, assetdb_allow_archive=false, platform_allow_mutations=false)
197
+ - `unrestricted` - Full access profile with all tools enabled
198
+
199
+ ## Important Advice
200
+
201
+ - When running python in this project, always use "uv run python".
202
+ - When you've made code changes, verify them with "just test" and "just lint".
203
+ - Use `just install` to set up the development environment and generate `.mcp.json` automatically.
204
+ - You will find it useful to have access to the Redash source code as you work; this
205
+ project talks to `https://github.com/stacklet/redash`, NOT the upstream project by
206
+ `getredash`. Cloning that repository into a temp directory and using the filesystem
207
+ is the most effective way to answer questions about redash implementation details.
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: stacklet-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for the Stacklet environment
5
+ Classifier: Programming Language :: Python :: 3 :: Only
6
+ Classifier: Programming Language :: Python :: 3.12
7
+ Classifier: Programming Language :: Python :: 3.13
8
+ Requires-Python: >=3.12
9
+ Requires-Dist: fastmcp>=2
10
+ Requires-Dist: graphql-core>=3.2
11
+ Requires-Dist: httpx>=0.28.1
12
+ Requires-Dist: pydantic-settings>=2.10.1
13
+ Requires-Dist: pydantic>=2.11.7
@@ -0,0 +1,115 @@
1
+ # Stacklet MCP Server
2
+
3
+ This is the MCP (Model Context Protocol) server for the Stacklet environment.
4
+ It exposes toolsets for granting LLMs the powers of:
5
+
6
+ * AssetDB SQL queries (ad-hoc and saved)
7
+ * Platform GraphQL operations (and export of large datasets)
8
+ * Documentation access (in .md, for context)
9
+
10
+ Each of the toolsets has an "info" tool with useful context, available to any client which supports minimal MCP features.
11
+ Asking your agent to tell you about a toolset is a fairly reliable way to get it to call the info tool and load up its context with relevant information.
12
+
13
+ **WARNING**: most Stacklet installations contain confidential data; this server largely exists to feed that data to your agent's LLM, which is generally running in a datacenter _Somewhere_. Be very confident in your understanding of all relevant data security policies before running this server.
14
+
15
+ **FURTHER WARNING**: when running with default settings, the worst an LLM can do with this server is make ill-advised queries, which is often regrettable but generally no worse than a well-intentioned human user might do.
16
+
17
+ By enabling the `_ALLOW_` options documented below, you are granting an LLM free rein to do _anything_ you could do with Stacklet; doing so naturally bears risks proportional to your own level of access. Strongly consider authenticating as a custom Stacklet user with permissions tightly scoped to your task as an additional safeguard.
18
+
19
+
20
+ ## Installation
21
+
22
+ The easiest way to get the `stacklet-mcp` binary is via `pip` or `uv`, with
23
+
24
+ ```
25
+ pip install stacklet-mcp
26
+ ```
27
+
28
+ or
29
+
30
+ ```
31
+ uv tool install stacklet-mcp
32
+ ```
33
+
34
+ Once installed, an agent configuration file (`.mcp.json`) can be generated with
35
+
36
+ ```
37
+ stacklet-mcp agent-config generate $profile
38
+ ```
39
+
40
+ where `$profile` can be either default (no edit allowed) or `unrestricted` (all edits allowed).
41
+ The configuration can be manually tweaked to just allow some edits.
42
+
43
+
44
+ ## Authentication
45
+
46
+ The MCP server needs to be authenticated wtih the Stacklet environment before use.
47
+ The easiest way to authenticate to your Stacklet environment is to use the [stacklet-admin](https://pypi.org/project/stacklet.client.platform/) command, which is most easily installed with:
48
+
49
+ ```
50
+ uv tool install stacklet.client.platform
51
+ ```
52
+
53
+ Once you've configured that, a
54
+
55
+ ```
56
+ stacklet-admin login
57
+ ```
58
+
59
+ will grant the MCP server access as the authenticated user for twelve hours. Leaving aside the default blocks on saving queries and mutating platform, the server will have the same powers and restrictions as that user.
60
+
61
+
62
+ ## Server configuration
63
+
64
+ The MCP server can be configured via environment variables.
65
+
66
+ When the MCP is run from an agent, those can be set in the `"env"` section of the `.mcp.json` file.
67
+
68
+ The following variables are available:
69
+
70
+ - `STACKLET_MCP_DOWNLOADS_PATH`: directory for storing query result files (default: system temp directory)
71
+ - `STACKLET_MCP_ASSETDB_DATASOURCE`: the datasource ID for AssetDB in Redash (default: `1`)
72
+ - `STACKLET_MCP_ASSETDB_ALLOW_SAVE`: whether to enable write operations in AssetDB (default: `false`)
73
+ - `STACKLET_MCP_ASSETDB_ALLOW_ARCHIVE`: whether to enable query archiving functionality in AssetDB (default: `false`)
74
+ - `STACKLET_MCP_PLATFORM_ALLOW_MUTATIONS`: whether to enable executing mutations in Platform API (default: `false`)
75
+
76
+
77
+ ## Development
78
+
79
+ For development, a few setup steps are required:
80
+
81
+
82
+ 1) install required tools. The easiest way is through [Mise](https://mise.jdx.dev/):
83
+
84
+ ```
85
+ mise install
86
+ ```
87
+
88
+ 2) install dependencies via
89
+
90
+ ```
91
+ just install
92
+ ```
93
+
94
+ This will also create a default`.mcp.json` (so long as there's nothing there already) with default read-only settings, which enables convenient experimentation by running e.g. [Claude Code](https://claude.com/product/claude-code)) in the project root without risk of altering saved AssetDB queries or running Platform mutations.
95
+
96
+ For alternative integrations, the `.mcp.json` file should serve as a starting point, but the details may vary by context; the best documentation for the format itself seems to be [here](https://gofastmcp.com/integrations/mcp-json-configuration#mcp-json-configuration-standard).
97
+
98
+
99
+ 3) Authenticate to the deployment as described above.
100
+
101
+ 4) Run the MCP server with
102
+
103
+ ```
104
+ just run [options...]
105
+ ```
106
+
107
+
108
+ ### Inspect MCP protocol
109
+
110
+
111
+ The MCP Protocol Inspector is invaluable for peeking at the details of the protocol in use. It can be run via
112
+
113
+ ```
114
+ just inspect
115
+ ```
@@ -0,0 +1,42 @@
1
+ # Setup development environment
2
+ install:
3
+ #!/usr/bin/env bash
4
+ set -e
5
+
6
+ uv sync
7
+ if [ ! -e .mcp.json ]; then
8
+ just agent-config
9
+ echo "Wrote .mcp.json"
10
+ fi
11
+
12
+ # Run the MCP server locally
13
+ run *args:
14
+ uv run stacklet-mcp {{args}}
15
+
16
+ # Run code formatters/linters
17
+ lint:
18
+ uv run pre-commit run --all-files
19
+
20
+ # Run tests
21
+ test *args:
22
+ uv run pytest {{args}}
23
+
24
+ # Run tests with coverage
25
+ test-coverage *args:
26
+ just test --cov {{args}}
27
+
28
+ # Run mcp-inspector
29
+ inspect:
30
+ npx @modelcontextprotocol/inspector just run
31
+
32
+ # Generate agent configuration (.mcp.json)
33
+ agent-config profile="default":
34
+ just run agent-config generate {{profile}} > .mcp.json
35
+
36
+ # Tag current commit with a release tag based on the project version
37
+ tag-release:
38
+ #!/usr/bin/env bash
39
+ set -e
40
+
41
+ version="$(uv run python -c 'from stacklet.mcp import __version__; print(__version__)')"
42
+ git tag -a "v$version" -m "Version $version"
@@ -0,0 +1 @@
1
+ Copyright (c) $create_year$year_delimiter$edit_year Stacklet, Inc.
@@ -0,0 +1,74 @@
1
+ [build-system]
2
+ build-backend = "hatchling.build"
3
+
4
+ requires = [ "hatchling" ]
5
+
6
+ [project]
7
+ name = "stacklet-mcp"
8
+ description = "MCP server for the Stacklet environment"
9
+ requires-python = ">=3.12"
10
+ classifiers = [
11
+ "Programming Language :: Python :: 3 :: Only",
12
+ "Programming Language :: Python :: 3.12",
13
+ "Programming Language :: Python :: 3.13",
14
+ ]
15
+ dynamic = [ "version" ]
16
+
17
+ dependencies = [
18
+ "fastmcp>=2",
19
+ "graphql-core>=3.2",
20
+ "httpx>=0.28.1",
21
+ "pydantic>=2.11.7",
22
+ "pydantic-settings>=2.10.1",
23
+ ]
24
+ scripts.stacklet-mcp = "stacklet.mcp.mcp:main"
25
+
26
+ [dependency-groups]
27
+ dev = [
28
+ "add-license-header>=2.4",
29
+ "mypy>=1.8",
30
+ "pre-commit>=4.2",
31
+ "pyproject-fmt>=2.6",
32
+ "pytest>=7",
33
+ "pytest-asyncio>=0.21",
34
+ "pytest-cov>=7",
35
+ "ruff>=0.12",
36
+ ]
37
+
38
+ [tool.hatch.version]
39
+ path = "stacklet/mcp/__init__.py"
40
+
41
+ [tool.hatch.build.targets.wheel]
42
+ packages = [ "stacklet" ]
43
+
44
+ [tool.ruff]
45
+ line-length = 100
46
+
47
+ # Add `line-too-long` and isort to the enforced rule set.
48
+ lint.extend-select = [ "E501", "I" ]
49
+ lint.isort.lines-after-imports = 2
50
+ # Use a single line between direct and from import.
51
+ lint.isort.lines-between-types = 1
52
+
53
+ [tool.pytest.ini_options]
54
+ asyncio_mode = "auto"
55
+ addopts = "--no-cov-on-fail"
56
+
57
+ [tool.coverage.report]
58
+ fail_under = 94.0
59
+ show_missing = true
60
+ skip_covered = true
61
+
62
+ [tool.mypy]
63
+ strict = true
64
+ install_types = true
65
+ warn_return_any = true
66
+ warn_unused_configs = true
67
+ check_untyped_defs = true
68
+ warn_redundant_casts = true
69
+ warn_unused_ignores = true
70
+ warn_no_return = true
71
+ ignore_missing_imports = true
72
+ non_interactive = true
73
+ exclude = [ "tests/" ]
74
+ plugins = [ "pydantic.mypy" ]
@@ -0,0 +1,8 @@
1
+ # LICENSE HEADER MANAGED BY add-license-header
2
+ #
3
+ # Copyright (c) 2025 Stacklet, Inc.
4
+ #
5
+
6
+ """Stacklet MCP server."""
7
+
8
+ __version__ = "0.1.0"
@@ -0,0 +1,11 @@
1
+ # LICENSE HEADER MANAGED BY add-license-header
2
+ #
3
+ # Copyright (c) 2025 Stacklet, Inc.
4
+ #
5
+
6
+ """Entry point for running the server from the package."""
7
+
8
+ from .mcp import main
9
+
10
+
11
+ main()
@@ -0,0 +1,4 @@
1
+ # LICENSE HEADER MANAGED BY add-license-header
2
+ #
3
+ # Copyright (c) 2025 Stacklet, Inc.
4
+ #