ai-credits-mcp
README.md
# ai-credits-mcp
MCP server that exposes AI credit usage data from OpenMeter to the TAIS AI chat service. Queries are automatically scoped to the calling tenant and restricted to admin users.
---
## Tools
All tools require the caller to be in the `Administrators` group. Each tool returns a markdown table (for the LLM to summarise) and a `[Download Excel](url)` link pointing to a temporary `.xlsx` file served at `/download/<token>`. The link expires after **10 minutes**. They are automatically scoped to the calling user's tenant — no tenant parameter is exposed.
If the request exceeds 50 rows in the text preview, the table is truncated with a note to see the Excel file for the full dataset.
### `get_credit_usage_by_tenant`
Returns total credits consumed by the tenant as a single aggregated number.
| Parameter | Type | Required | Description |
|---|---|---|---|
| `from_date` | string | No | ISO 8601 start, e.g. `"2026-01-01T00:00:00Z"` |
| `to_date` | string | No | ISO 8601 end (defaults to now) |
**Output columns:** `tenant`, `credits`
**Example prompts:**
- *"How many AI credits has my tenant used?"*
- *"What's our total credit spend this month?"*
---
### `get_credit_usage_summary`
Returns credits broken down by user, module, product, and skill — useful for identifying who or what is consuming the most credits.
| Parameter | Type | Required | Description |
|---|---|---|---|
| `from_date` | string | No | ISO 8601 start |
| `to_date` | string | No | ISO 8601 end (defaults to now) |
**Output columns:** `user`, `module`, `product`, `tenant`, `skill`, `credits`
**Example prompts:**
- *"Show me credit usage broken down by user."*
- *"Which product or skill is using the most credits?"*
- *"Give me a credit usage summary for Q1 2026."*
---
### `get_credit_events`
Returns individual raw credit events — the lowest level of detail, one row per event.
| Parameter | Type | Required | Description |
|---|---|---|---|
| `from_date` | string | No | ISO 8601 start |
| `to_date` | string | No | ISO 8601 end (defaults to now) |
**Output columns:** `time`, `user`, `module`, `product`, `tenant`, `credits`
**Example prompts:**
- *"Show me all credit events from last week."*
- *"What happened on January 15th in terms of AI usage?"*
---
### How the AI decides which tool to call
When you ask about credit usage in the AI chat, the model picks the appropriate tool automatically:
- Totals / "how much overall" → `get_credit_usage_by_tenant`
- Breakdowns by user / module / skill → `get_credit_usage_summary`
- Individual events / audit trail → `get_credit_events`
If no date range is specified, the last 7 days are used by default. To change the range, phrase your question naturally: *"...for January 2026"* or *"...since last month"* — the model will translate this to ISO 8601 parameters.
---
## Security
| Invariant | Enforcement |
|---|---|
| Admin-only access | `X-User-UserRole` checked on every call; accepted values: `admin`, `Administrators` |
| Tenant-scoped | `X-Tenant-Name` header used as filter; callers cannot override it |
| Tenant header absent | Returns an error — no data is exposed |
| `OPENMETER_API_KEY` never exposed | Only used inside `query_credits._get()`; never returned to callers |
The TAIS chatbot-agent-service forwards both headers automatically on every MCP connection.
---
## Running locally
**Prerequisites:** Python 3.11+, `uv`
```bash
cd ai-credits-mcp
uv sync # install dependencies
cp .env.example .env # add your OPENMETER_API_KEY
uv run main.py
# Server starts at http://localhost:8765
```
Health check:
```bash
curl http://localhost:8765/health
# {"status": "ok"}
```
---
## AI chat integration
Use the registration script to register the tool and wire it to a TAIS session:
```bash
bash scripts/register.sh
```
The script reads `TAIS_JWT` from `.env`, decodes the tenant and user automatically, registers the tool against the local TAIS API, and PATCHes the session. If `TAIS_SESSION_ID` is not set in `.env` it will prompt you interactively.
**Note:** registered tools expire after ~1 hour. Re-run the script when the tool stops responding.
To wire to a session manually:
```bash
PATCH http://localhost:5001/api/v2/sessions-service/{sessionId}
Authorization: Bearer <token>
Content-Type: application/json
{"toolIds": ["<tool-id-from-registration>"]}
```
---
## Environment variables
| Variable | Required | Description |
|---|---|---|
| `OPENMETER_API_KEY` | Yes | OpenMeter API key |
| `MCP_PORT` | No | Port to listen on (default: `8765`) |
| `TAIS_JWT` | No | JWT for `scripts/register.sh` — not used by the server at runtime |
| `TAIS_SESSION_ID` | No | Session to wire the tool to; script prompts if absent |
| `TENANT_OVERRIDE` | No | Dev only — overrides `X-Tenant-Name` header |
| `ROLE_OVERRIDE` | No | Dev only — overrides `X-User-UserRole` header |
---
## Project structure
```
ai-credits-mcp/
├── server.py # FastMCP server, tools, middleware, download endpoint
├── main.py # uvicorn entry point
├── scripts/
│ └── register.sh # registers tool with TAIS and wires it to a session
├── pyproject.toml # dependencies (mcp, uvicorn, openpyxl, python-dotenv)
└── .env.example # environment variable template
```
`server.py` imports `query_credits` from the sibling `ai-credit-usage/` directory, which handles all OpenMeter API calls.
---
## Aspire registration
Registered in `apphost.cs` as:
```csharp
var aiCreditsMcp = builder.AddPythonApp("ai-credits-mcp", "/Users/a.demers/dev/ai-credits-mcp", "main.py")
.WithUv()
.WithEnvironment("PYTHONPATH", ".")
.WithHttpEndpoint(port: 8765, env: "MCP_PORT", isProxied: false)
.WithHttpHealthCheck("/health")
.WithEnvironment("OPENMETER_API_KEY", Environment.GetEnvironmentVariable("OPENMETER_API_KEY") ?? "");
```
Add `OPENMETER_API_KEY=<your-key>` to the workspace-root `.env` file.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues