blob: a320af48c7211e0643f6d06f22d11473450e5def [file] [view]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Apache Polaris MCP Server
This package provides a Python implementation of the [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for Apache Polaris. It wraps the Polaris REST APIs so MCP-compatible clients (IDEs, agents, chat applications) can issue structured requests via JSON-RPC on stdin/stdout.
The implementation is built on top of [FastMCP](https://gofastmcp.com) for streamlined server registration and transport handling.
## Prerequisites
- Python 3.10 or later
- [uv](https://docs.astral.sh/uv/) 0.9.7 or later
## Building and Running
Run the following commands from the `mcp-server` directory:
- `uv sync` - install runtime dependencies
- `uv run polaris-mcp` - start the MCP server (stdin/stdout transport)
- `uv sync --all-extras` - install runtime and dev dependencies
- `uv run pytest` - run the test suite
- `uv run pre-commit run --all-files` - lint all files
- `uv build && uv publish --index testpypi --token [Pypi-API-token]` - Publish a nightly to test.pypi.org
- `uv build && uv publish --index pypi --token [Pypi-API-token]` - Publish a formal binary release to pypi.org
For a `tools/call` invocation you will typically set environment variables such as `POLARIS_BASE_URL` and authentication settings before launching the server. A default `.polaris_mcp.env` file is included on the tool root directory, and any of the configuration variables can be specified in this file. After adding configuration variables to the `.polaris_mcp.env` file, explicitly setting these is no longer needed. However, shell environment variables will always take precedence if provided.
### Claude Desktop configuration
```json
{
"mcpServers": {
"polaris": {
"command": "uv",
"args": [
"--directory",
"/path/to/polaris-tools/mcp-server",
"run",
"polaris-mcp"
],
"env": {
"POLARIS_CONFIG_FILE": "/path/to/polaris-tools/mcp-server/.polaris_mcp.env"
}
}
}
}
```
Please note: `--directory` specifies a local directory. It is not needed when we pull `polaris-mcp` from PyPI package.
### MCP Client
For quick local testing without configuring a full client like Claude Desktop, you can use the included `client.py` script.
```bash
# Start client in interactative mode with STDIO transport
uv run int_test/client.py polaris_mcp/server.py
```
You can also run client directly from the command line with non-interactive mode:
```bash
uv run int_test/client.py http://localhost:8000/mcp --tool polaris-catalog-request --args '{"operation": "list"}'
```
Here are sample client commands:
```bash
# Create catalog
uv run int_test/client.py polaris_mcp/server.py \
--tool polaris-catalog-request \
--args '{
"operation": "create",
"body": {
"catalog": {
"name": "quickstart_catalog",
"type": "INTERNAL",
"readOnly": false,
"properties": {
"default-base-location": "s3://bucket123"
},
"storageConfigInfo": {
"storageType": "S3",
"allowedLocations": ["s3://bucket123"],
"endpoint": "http://localhost:9000",
"pathStyleAccess": true
}
}
}
}'
# List catalog
uv run int_test/client.py polaris_mcp/server.py \
--tool polaris-catalog-request \
--args '{"operation": "list"}'
# List catalog in realm "POLARIS"
uv run int_test/client.py polaris_mcp/server.py \
--tool polaris-catalog-request \
--args '{"operation": "list", "realm": "POLARIS"}'
# Create principal
uv run int_test/client.py polaris_mcp/server.py \
--tool polaris-principal-request \
--args '{
"operation": "create",
"body": {
"principal": {
"name": "quickstart_user",
"properties": {}
}
}
}'
# Create principal role
uv run int_test/client.py polaris_mcp/server.py \
--tool polaris-principal-role-request \
--args '{
"operation": "create",
"body": {
"principalRole": {
"name": "quickstart_user_role",
"properties": {}
}
}
}'
# Assign principal role
uv run int_test/client.py polaris_mcp/server.py \
--tool polaris-principal-request \
--args '{
"operation": "assign-principal-role",
"principal": "quickstart_user",
"body": {
"principalRole": {
"name": "quickstart_user_role"
}
}
}'
```
## Configuration
| Variable | Description | Default |
|----------------------------------------------------------------|------------------------------------------------------------------|--------------------------------------------------|
| `POLARIS_BASE_URL` | Base URL for all Polaris REST calls. | `http://localhost:8181/` |
| `POLARIS_API_TOKEN` / `POLARIS_BEARER_TOKEN` / `POLARIS_TOKEN` | Static bearer token (if supplied, overrides other auth). | _unset_ |
| `POLARIS_CLIENT_ID` | OAuth client id for client-credential flow. | _unset_ |
| `POLARIS_CLIENT_SECRET` | OAuth client secret. | _unset_ |
| `POLARIS_TOKEN_SCOPE` | OAuth scope string. | _unset_ |
| `POLARIS_TOKEN_URL` | Optional override for the token endpoint URL. | `${POLARIS_BASE_URL}api/catalog/v1/oauth/tokens` |
| `POLARIS_REALM_{realm}_CLIENT_ID` | OAuth client id for a specific realm. | _unset_ |
| `POLARIS_REALM_{realm}_CLIENT_SECRET` | OAuth client secret for a specific realm. | _unset_ |
| `POLARIS_REALM_{realm}_TOKEN_SCOPE` | OAuth scope for a specific realm. | _unset_ |
| `POLARIS_REALM_{realm}_TOKEN_URL` | Token endpoint URL for a specific realm. | _unset_ |
| `POLARIS_REALM_CONTEXT_HEADER_NAME` | Header name used for realm context. | `Polaris-Realm` |
| `POLARIS_TOKEN_REFRESH_BUFFER_SECONDS` | Minimum remaining token lifetime before refreshing in seconds. | `60.0` |
| `POLARIS_HTTP_TIMEOUT_SECONDS` | Default timeout in seconds for all HTTP requests. | `30.0` |
| `POLARIS_HTTP_CONNECT_TIMEOUT_SECONDS` | Timeout in seconds for establishing HTTP connections. | `30.0` |
| `POLARIS_HTTP_READ_TIMEOUT_SECONDS` | Timeout in seconds for reading HTTP responses. | `30.0` |
| `POLARIS_HTTP_RETRIES_TOTAL` | Total number of retries for HTTP requests. | `3` |
| `POLARIS_HTTP_RETRIES_BACKOFF_FACTOR` | Factor for exponential backoff between retries. | `0.5` |
| `POLARIS_CONFIG_FILE` | Path to a configuration file containing configuration variables. | `.polaris_mcp.env` in current working directory |
When OAuth variables are supplied, the server automatically acquires and refreshes tokens using the client credentials flow; otherwise a static bearer token is used if provided.
Realm-specific variables (e.g., `POLARIS_REALM_${realm}_CLIENT_ID`) override the global settings for a given realm for client ID, client secret, token scope, and token URL. If realm-specific credentials are provided but incomplete, the server will not fall back to global credentials for that realm.
## Tools
The server exposes the following MCP tools:
* `polaris-iceberg-table-request` — Perform table operations (`list`, `get`, `create`, `update`, `delete`).
* `polaris-namespace-request` — Perform namespace operations (`list`, `get`, `create`, `exists`, `get-properties`, `delete`).
* `polaris-policy-request` — Perform policy operations (`list`, `get`, `create`, `update`, `delete`, `attach`, `detach`, `applicable`).
* `polaris-catalog-request` — Perform catalog operations (`list`, `get`, `create`, `update`, `delete`).
* `polaris-principal-request` — Perform principal operations (`list`, `get`, `create`, `update`, `delete`, `rotate`, `reset`, `list-roles`, `assign-role`, `revoke-role`).
* `polaris-principal-role-request` — Perform principal role operations (`list`, `get`, `create`, `update`, `delete`, `list-assignees`, `list-catalog-roles`, `assign-catalog-role`, `revoke-catalog-role`).
* `polaris-catalog-role-request` — Perform catalog role operations (`list`, `get`, `create`, `update`, `delete`, `list-principal-roles`, `list-grants`, `add-grant`, `revoke-grant`).
Each tool returns both a human-readable transcript of the HTTP exchange and structured metadata under `result.meta`.