@occam-scaly/mcp-server 0.1.2
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.
- package/README.md +166 -0
- package/bin/scaly-mcp.js +6 -0
- package/dist/audit.d.ts +25 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +182 -0
- package/dist/audit.js.map +1 -0
- package/dist/client.d.ts +16 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +142 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +76 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +279 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/index.d.ts +17 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +505 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/tools/addons.d.ts +3 -0
- package/dist/tools/addons.d.ts.map +1 -0
- package/dist/tools/addons.js +128 -0
- package/dist/tools/addons.js.map +1 -0
- package/dist/tools/apps.d.ts +3 -0
- package/dist/tools/apps.d.ts.map +1 -0
- package/dist/tools/apps.js +121 -0
- package/dist/tools/apps.js.map +1 -0
- package/dist/tools/compute.d.ts +3 -0
- package/dist/tools/compute.d.ts.map +1 -0
- package/dist/tools/compute.js +135 -0
- package/dist/tools/compute.js.map +1 -0
- package/dist/tools/db.d.ts +3 -0
- package/dist/tools/db.d.ts.map +1 -0
- package/dist/tools/db.js +597 -0
- package/dist/tools/db.js.map +1 -0
- package/dist/tools/deployments.d.ts +3 -0
- package/dist/tools/deployments.d.ts.map +1 -0
- package/dist/tools/deployments.js +354 -0
- package/dist/tools/deployments.js.map +1 -0
- package/dist/tools/diagnose.d.ts +3 -0
- package/dist/tools/diagnose.d.ts.map +1 -0
- package/dist/tools/diagnose.js +213 -0
- package/dist/tools/diagnose.js.map +1 -0
- package/dist/tools/env.d.ts +3 -0
- package/dist/tools/env.d.ts.map +1 -0
- package/dist/tools/env.js +216 -0
- package/dist/tools/env.js.map +1 -0
- package/dist/tools/index.d.ts +38 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +48 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/jobs.d.ts +3 -0
- package/dist/tools/jobs.d.ts.map +1 -0
- package/dist/tools/jobs.js +160 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/logs.d.ts +3 -0
- package/dist/tools/logs.d.ts.map +1 -0
- package/dist/tools/logs.js +157 -0
- package/dist/tools/logs.js.map +1 -0
- package/dist/tools/operations.d.ts +3 -0
- package/dist/tools/operations.d.ts.map +1 -0
- package/dist/tools/operations.js +262 -0
- package/dist/tools/operations.js.map +1 -0
- package/dist/tools/project.d.ts +3 -0
- package/dist/tools/project.d.ts.map +1 -0
- package/dist/tools/project.js +341 -0
- package/dist/tools/project.js.map +1 -0
- package/dist/tools/s3.d.ts +3 -0
- package/dist/tools/s3.d.ts.map +1 -0
- package/dist/tools/s3.js +256 -0
- package/dist/tools/s3.js.map +1 -0
- package/dist/tools/status.d.ts +3 -0
- package/dist/tools/status.d.ts.map +1 -0
- package/dist/tools/status.js +139 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/tools/write.d.ts +3 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +900 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/utils/jwt.d.ts +3 -0
- package/dist/utils/jwt.d.ts.map +1 -0
- package/dist/utils/jwt.js +32 -0
- package/dist/utils/jwt.js.map +1 -0
- package/dist/utils/paths.d.ts +5 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +26 -0
- package/dist/utils/paths.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# @occam-scaly/mcp-server
|
|
2
|
+
|
|
3
|
+
Model Context Protocol (MCP) server for Scaly. Connect your AI assistant (Claude, Cursor, etc.) to manage your cloud infrastructure.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
Note: If `@occam-scaly/mcp-server` is not published to npm yet, run it from a local checkout of the Scaly repo (see “Development” below) and point your MCP client at `packages/mcp-server/bin/scaly-mcp.js`.
|
|
8
|
+
|
|
9
|
+
### 1. Get your API key
|
|
10
|
+
|
|
11
|
+
Go to **Scaly Dashboard → Settings → Integrations → AI Assistants** and generate:
|
|
12
|
+
|
|
13
|
+
- **Scaly API key** (`SCALY_API_KEY`)
|
|
14
|
+
- **AppSync API key** (`SCALY_APPSYNC_KEY`, optional for Scaly hosted `prod|dev|qa`)
|
|
15
|
+
|
|
16
|
+
Optional:
|
|
17
|
+
|
|
18
|
+
- **OIDC session token** (`SCALY_OIDC_TOKEN`) — required only for DB/S3 tools. Get it from Scaly Dashboard → Settings → Integrations → AI Integrations.
|
|
19
|
+
|
|
20
|
+
### 2. Configure your AI assistant
|
|
21
|
+
|
|
22
|
+
**Claude Desktop** - Add to `~/.config/claude/claude_desktop_config.json`:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mcpServers": {
|
|
27
|
+
"scaly": {
|
|
28
|
+
"command": "npx",
|
|
29
|
+
"args": ["-y", "@occam-scaly/mcp-server"],
|
|
30
|
+
"env": {
|
|
31
|
+
"SCALY_API_KEY": "sk_live_your_key_here",
|
|
32
|
+
"SCALY_APPSYNC_KEY": "da2_live_your_key_here (optional for Scaly hosted prod/dev/qa)",
|
|
33
|
+
"SCALY_OIDC_TOKEN": "eyJ... (optional, enables DB/S3 tools)",
|
|
34
|
+
"SCALY_STAGE": "prod"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Claude Code** - Add to your Claude Code MCP settings.
|
|
42
|
+
|
|
43
|
+
### 3. Restart your AI assistant
|
|
44
|
+
|
|
45
|
+
The Scaly tools will now be available.
|
|
46
|
+
|
|
47
|
+
## Available Tools
|
|
48
|
+
|
|
49
|
+
All tools return **JSON-only** responses (wrapped in MCP `content[].text`).
|
|
50
|
+
|
|
51
|
+
### Core inventory
|
|
52
|
+
|
|
53
|
+
- `scaly_status` - Overview of stacks/apps + running deployments
|
|
54
|
+
- `scaly_list_apps` / `scaly_get_app`
|
|
55
|
+
- `scaly_list_stacks` / `scaly_get_stack` (alias: `scaly_list_compute`)
|
|
56
|
+
- `scaly_list_addons` / `scaly_get_addon`
|
|
57
|
+
- `scaly_list_jobs` / `scaly_run_job`
|
|
58
|
+
|
|
59
|
+
### Deployments & operations
|
|
60
|
+
|
|
61
|
+
- `scaly_list_deployments` / `scaly_get_deployment` (alias: `scaly_get_deployment_status`)
|
|
62
|
+
- `scaly_deploy_app` (currently implemented as stack service restart)
|
|
63
|
+
- `scaly_restart_stack_services`
|
|
64
|
+
- `scaly_retry_deployment`
|
|
65
|
+
- `scaly_get_operation` / `scaly_wait_operation` / `scaly_get_operation_events`
|
|
66
|
+
|
|
67
|
+
### Configuration
|
|
68
|
+
|
|
69
|
+
- `scaly_set_env` (alias: `scaly_set_env_var`) – blocks secret-like keys, never echoes values
|
|
70
|
+
- `scaly_get_env_vars` – returns names only
|
|
71
|
+
|
|
72
|
+
### Project config
|
|
73
|
+
|
|
74
|
+
- `scaly_plan` – computes a plan from `.scaly/config.yaml` and returns `plan_hash`
|
|
75
|
+
- `scaly_apply` – applies a plan (requires `plan_hash` and `auto_approve: true`)
|
|
76
|
+
- `scaly_pull` – writes `.scaly/config.yaml` by reverse-engineering live state
|
|
77
|
+
|
|
78
|
+
### Write tools (imperative)
|
|
79
|
+
|
|
80
|
+
- `scaly_create_stack` / `scaly_update_stack` / `scaly_delete_stack` (preview-first; delete requires confirm)
|
|
81
|
+
- `scaly_create_database` / `scaly_create_storage` / `scaly_create_user_pool`
|
|
82
|
+
- `scaly_create_app`
|
|
83
|
+
- `scaly_link_addon`
|
|
84
|
+
- `scaly_configure_auth`
|
|
85
|
+
|
|
86
|
+
Notes:
|
|
87
|
+
|
|
88
|
+
- Phase 4 intentionally omits add-on updates/resizes, add-on deletion, and unlink operations.
|
|
89
|
+
|
|
90
|
+
### Logs & diagnostics
|
|
91
|
+
|
|
92
|
+
- `scaly_get_logs` (unified logs)
|
|
93
|
+
- `scaly_diagnose_app`
|
|
94
|
+
|
|
95
|
+
### Database & S3 (requires OIDC token)
|
|
96
|
+
|
|
97
|
+
- `scaly_db_query` / `scaly_db_execute`
|
|
98
|
+
- `scaly_db_migration_plan` / `scaly_db_migrate` / `scaly_db_schema_dump`
|
|
99
|
+
- `scaly_s3_list_objects` / `scaly_s3_download_object`
|
|
100
|
+
- `scaly_s3_upload_object` / `scaly_s3_delete_object` (currently NOT_SUPPORTED)
|
|
101
|
+
|
|
102
|
+
## Resources
|
|
103
|
+
|
|
104
|
+
- `scaly://capabilities` (YAML)
|
|
105
|
+
- `scaly://resources-schema` (JSON Schema)
|
|
106
|
+
- `scaly://guides/platform` (Markdown)
|
|
107
|
+
- `scaly://guides/golden-paths` (Markdown)
|
|
108
|
+
- Templates: `scaly://guides/frameworks/{name}`, `scaly://guides/patterns/{name}`, `scaly://apps/{id}`, `scaly://stacks/{id}`
|
|
109
|
+
|
|
110
|
+
## Example Usage
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
You: "What apps do I have running?"
|
|
114
|
+
|
|
115
|
+
Claude: [Calling scaly_list_apps]
|
|
116
|
+
|
|
117
|
+
{"success":true,"data":{"apps":[...],"count":3},"meta":{...}}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
You: "Deploy ml-api"
|
|
122
|
+
|
|
123
|
+
Claude: [Calling scaly_deploy_app]
|
|
124
|
+
|
|
125
|
+
{"success":true,"data":{"operation_id":"dep_abc123",...},"meta":{...}}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Environment Variables
|
|
129
|
+
|
|
130
|
+
| Variable | Required | Description |
|
|
131
|
+
| ---------------------- | -------- | ---------------------------------------------------------------- |
|
|
132
|
+
| `SCALY_API_KEY` | Yes | Your Scaly API key |
|
|
133
|
+
| `SCALY_APPSYNC_KEY` | No | AppSync API key (enables API access; defaults for prod/dev/qa) |
|
|
134
|
+
| `SCALY_OIDC_TOKEN` | No | Cognito access token (enables DB/S3 tools) |
|
|
135
|
+
| `SCALY_MCP_AUDIT` | No | Enable audit logging (`true` by default; set `false` to disable) |
|
|
136
|
+
| `SCALY_MCP_AUDIT_FILE` | No | Write audit logs as JSONL to this file path (defaults to stderr) |
|
|
137
|
+
| `SCALY_STAGE` | No | `prod` (default), `dev`, `qa` (`staging` alias) |
|
|
138
|
+
| `SCALY_API_URL` | No | Override API URL |
|
|
139
|
+
|
|
140
|
+
## Development
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# Install dependencies
|
|
144
|
+
npm install
|
|
145
|
+
|
|
146
|
+
# Run in development mode
|
|
147
|
+
npm run dev
|
|
148
|
+
|
|
149
|
+
# Build
|
|
150
|
+
npm run build
|
|
151
|
+
|
|
152
|
+
# Type check
|
|
153
|
+
npm run typecheck
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Security
|
|
157
|
+
|
|
158
|
+
- API keys are scoped to specific permissions
|
|
159
|
+
- Tool outputs are treated as durable transcripts; avoid returning secrets or credentials
|
|
160
|
+
- Never store API keys in version control
|
|
161
|
+
- Revoke keys immediately if compromised
|
|
162
|
+
|
|
163
|
+
## Support
|
|
164
|
+
|
|
165
|
+
- Documentation: https://docs.scaly.cloud/mcp
|
|
166
|
+
- Issues: https://github.com/scaly-cloud/mcp-server/issues
|
package/bin/scaly-mcp.js
ADDED
package/dist/audit.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type AuditKind = 'tool_call' | 'resource_read';
|
|
2
|
+
type AuditEvent = {
|
|
3
|
+
kind: AuditKind;
|
|
4
|
+
ts: string;
|
|
5
|
+
request_id: string;
|
|
6
|
+
stage?: string;
|
|
7
|
+
api_url?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
uri?: string;
|
|
10
|
+
input?: unknown;
|
|
11
|
+
success: boolean;
|
|
12
|
+
error_code?: string;
|
|
13
|
+
duration_ms: number;
|
|
14
|
+
output?: unknown;
|
|
15
|
+
};
|
|
16
|
+
export declare function createAuditLogger({ stage, apiUrl }: {
|
|
17
|
+
stage?: string;
|
|
18
|
+
apiUrl?: string;
|
|
19
|
+
}): {
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
logToolCall: (e: Omit<AuditEvent, "kind" | "ts" | "stage" | "api_url">) => void;
|
|
22
|
+
logResourceRead: (e: Omit<AuditEvent, "kind" | "ts" | "stage" | "api_url">) => void;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAIA,KAAK,SAAS,GAAG,WAAW,GAAG,eAAe,CAAC;AAE/C,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAgJF,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,MAAM,EACP,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;qBAqBoB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,GAAG,SAAS,CAAC;yBAWjE,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,GAAG,SAAS,CAAC;EAY7D"}
|
package/dist/audit.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createAuditLogger = createAuditLogger;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
10
|
+
function parseBoolEnv(value, defaultValue) {
|
|
11
|
+
if (value === undefined)
|
|
12
|
+
return defaultValue;
|
|
13
|
+
const v = value.trim().toLowerCase();
|
|
14
|
+
if (['1', 'true', 'yes', 'y', 'on'].includes(v))
|
|
15
|
+
return true;
|
|
16
|
+
if (['0', 'false', 'no', 'n', 'off'].includes(v))
|
|
17
|
+
return false;
|
|
18
|
+
return defaultValue;
|
|
19
|
+
}
|
|
20
|
+
function sha256(text) {
|
|
21
|
+
return (0, node_crypto_1.createHash)('sha256').update(text).digest('hex');
|
|
22
|
+
}
|
|
23
|
+
function summarizeString(value) {
|
|
24
|
+
const maxLen = 200;
|
|
25
|
+
if (value.length <= maxLen)
|
|
26
|
+
return value;
|
|
27
|
+
return { truncated: true, length: value.length, sha256: sha256(value) };
|
|
28
|
+
}
|
|
29
|
+
function redactValue(value, keyPath) {
|
|
30
|
+
const key = keyPath[keyPath.length - 1] || '';
|
|
31
|
+
const lower = key.toLowerCase();
|
|
32
|
+
// Always redact env var values and similar.
|
|
33
|
+
if (lower === 'value')
|
|
34
|
+
return '[REDACTED]';
|
|
35
|
+
// Avoid logging SQL or params verbatim (may contain sensitive data).
|
|
36
|
+
if (lower === 'sql' && typeof value === 'string') {
|
|
37
|
+
return {
|
|
38
|
+
redacted: true,
|
|
39
|
+
bytes: Buffer.byteLength(value, 'utf8'),
|
|
40
|
+
sha256: sha256(value)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (lower === 'params' && Array.isArray(value)) {
|
|
44
|
+
return value.map((v) => {
|
|
45
|
+
if (typeof v === 'string') {
|
|
46
|
+
return {
|
|
47
|
+
type: 'string',
|
|
48
|
+
bytes: Buffer.byteLength(v, 'utf8'),
|
|
49
|
+
sha256: sha256(v)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (typeof v === 'number')
|
|
53
|
+
return { type: 'number' };
|
|
54
|
+
if (typeof v === 'boolean')
|
|
55
|
+
return { type: 'boolean' };
|
|
56
|
+
if (v === null)
|
|
57
|
+
return { type: 'null' };
|
|
58
|
+
if (Array.isArray(v))
|
|
59
|
+
return { type: 'array' };
|
|
60
|
+
if (typeof v === 'object')
|
|
61
|
+
return { type: 'object' };
|
|
62
|
+
return { type: typeof v };
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// Redact common credential-like fields by name (avoid matching "key" which is often non-secret, e.g., S3 object keys).
|
|
66
|
+
if (/(secret|token|password|credential|authorization|cookie)/i.test(lower)) {
|
|
67
|
+
return '[REDACTED]';
|
|
68
|
+
}
|
|
69
|
+
if (typeof value === 'string')
|
|
70
|
+
return summarizeString(value);
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
function redactObject(value, keyPath = [], depth = 0) {
|
|
74
|
+
const maxDepth = 6;
|
|
75
|
+
if (depth > maxDepth)
|
|
76
|
+
return '[TRUNCATED]';
|
|
77
|
+
if (Array.isArray(value)) {
|
|
78
|
+
return value.map((v) => redactObject(v, keyPath, depth + 1));
|
|
79
|
+
}
|
|
80
|
+
if (value && typeof value === 'object') {
|
|
81
|
+
const out = {};
|
|
82
|
+
for (const [k, v] of Object.entries(value)) {
|
|
83
|
+
out[k] = redactObject(redactValue(v, [...keyPath, k]), [...keyPath, k], depth + 1);
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
return redactValue(value, keyPath);
|
|
88
|
+
}
|
|
89
|
+
function summarizeOutput(value) {
|
|
90
|
+
if (!value || typeof value !== 'object')
|
|
91
|
+
return value;
|
|
92
|
+
const obj = value;
|
|
93
|
+
// Avoid logging potentially large/sensitive payloads.
|
|
94
|
+
const denyKeys = new Set([
|
|
95
|
+
'rows',
|
|
96
|
+
'events',
|
|
97
|
+
'logs',
|
|
98
|
+
'content',
|
|
99
|
+
'schema',
|
|
100
|
+
'stdout',
|
|
101
|
+
'stderr'
|
|
102
|
+
]);
|
|
103
|
+
const allowKeys = new Set([
|
|
104
|
+
'operation_id',
|
|
105
|
+
'app_id',
|
|
106
|
+
'stack_id',
|
|
107
|
+
'addon_id',
|
|
108
|
+
'account_id',
|
|
109
|
+
'output_path',
|
|
110
|
+
'migration_path',
|
|
111
|
+
'count',
|
|
112
|
+
'row_count',
|
|
113
|
+
'row_count_returned',
|
|
114
|
+
'row_count_reported',
|
|
115
|
+
'bytes',
|
|
116
|
+
'bytes_written',
|
|
117
|
+
'command',
|
|
118
|
+
'preview',
|
|
119
|
+
'dangerous',
|
|
120
|
+
'reasons',
|
|
121
|
+
'truncated',
|
|
122
|
+
'next_cursor',
|
|
123
|
+
'next_cursor_token',
|
|
124
|
+
'next_cursor_page_token',
|
|
125
|
+
'next_page_token',
|
|
126
|
+
'next_token'
|
|
127
|
+
]);
|
|
128
|
+
const summary = {};
|
|
129
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
130
|
+
if (denyKeys.has(k))
|
|
131
|
+
continue;
|
|
132
|
+
if (allowKeys.has(k))
|
|
133
|
+
summary[k] = redactObject(v, [k]);
|
|
134
|
+
}
|
|
135
|
+
// If nothing matched, at least return top-level keys (no values).
|
|
136
|
+
if (Object.keys(summary).length === 0) {
|
|
137
|
+
return { keys: Object.keys(obj).slice(0, 50) };
|
|
138
|
+
}
|
|
139
|
+
return summary;
|
|
140
|
+
}
|
|
141
|
+
function createAuditLogger({ stage, apiUrl }) {
|
|
142
|
+
const enabled = parseBoolEnv(process.env.SCALY_MCP_AUDIT, true);
|
|
143
|
+
const filePath = process.env.SCALY_MCP_AUDIT_FILE?.trim() || null;
|
|
144
|
+
const write = (event) => {
|
|
145
|
+
if (!enabled)
|
|
146
|
+
return;
|
|
147
|
+
const line = JSON.stringify(event);
|
|
148
|
+
if (filePath) {
|
|
149
|
+
try {
|
|
150
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(filePath), { recursive: true });
|
|
151
|
+
node_fs_1.default.appendFileSync(filePath, line + '\n', 'utf8');
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Fall back to stderr if file writing fails.
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
console.error(line);
|
|
159
|
+
};
|
|
160
|
+
return {
|
|
161
|
+
enabled,
|
|
162
|
+
logToolCall: (e) => write({
|
|
163
|
+
kind: 'tool_call',
|
|
164
|
+
ts: new Date().toISOString(),
|
|
165
|
+
stage,
|
|
166
|
+
api_url: apiUrl,
|
|
167
|
+
...e,
|
|
168
|
+
input: redactObject(e.input),
|
|
169
|
+
output: summarizeOutput(e.output)
|
|
170
|
+
}),
|
|
171
|
+
logResourceRead: (e) => write({
|
|
172
|
+
kind: 'resource_read',
|
|
173
|
+
ts: new Date().toISOString(),
|
|
174
|
+
stage,
|
|
175
|
+
api_url: apiUrl,
|
|
176
|
+
...e,
|
|
177
|
+
input: redactObject(e.input),
|
|
178
|
+
output: summarizeOutput(e.output)
|
|
179
|
+
})
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { GraphQLClient } from 'graphql-request';
|
|
2
|
+
import type { Config } from './config.js';
|
|
3
|
+
export declare function initClient(config: Config): GraphQLClient;
|
|
4
|
+
export declare function initOidcClient(config: Config): GraphQLClient | null;
|
|
5
|
+
export declare function getClient(): GraphQLClient;
|
|
6
|
+
export declare function getOidcClient(): GraphQLClient;
|
|
7
|
+
export declare function query<T>(gql: string, variables?: Record<string, unknown>): Promise<T>;
|
|
8
|
+
export declare function oidcQuery<T>(gql: string, variables?: Record<string, unknown>): Promise<T>;
|
|
9
|
+
export declare const FRAGMENTS: {
|
|
10
|
+
app: string;
|
|
11
|
+
stack: string;
|
|
12
|
+
deployment: string;
|
|
13
|
+
scheduledJob: string;
|
|
14
|
+
jobRun: string;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAK1C,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAYxD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAYnE;AAED,wBAAgB,SAAS,IAAI,aAAa,CAKzC;AAED,wBAAgB,aAAa,IAAI,aAAa,CAO7C;AAGD,wBAAsB,KAAK,CAAC,CAAC,EAC3B,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,CAAC,CAAC,CAYZ;AAED,wBAAsB,SAAS,CAAC,CAAC,EAC/B,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,CAAC,CAAC,CAWZ;AAGD,eAAO,MAAM,SAAS;;;;;;CA8DrB,CAAC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FRAGMENTS = void 0;
|
|
4
|
+
exports.initClient = initClient;
|
|
5
|
+
exports.initOidcClient = initOidcClient;
|
|
6
|
+
exports.getClient = getClient;
|
|
7
|
+
exports.getOidcClient = getOidcClient;
|
|
8
|
+
exports.query = query;
|
|
9
|
+
exports.oidcQuery = oidcQuery;
|
|
10
|
+
const graphql_request_1 = require("graphql-request");
|
|
11
|
+
let client = null;
|
|
12
|
+
let oidcClient = null;
|
|
13
|
+
function initClient(config) {
|
|
14
|
+
// Two-key auth:
|
|
15
|
+
// - x-api-key: AppSync API key (enables API access)
|
|
16
|
+
// - x-scaly-api-key: User's Scaly API key (for authorization/scopes)
|
|
17
|
+
client = new graphql_request_1.GraphQLClient(config.apiUrl, {
|
|
18
|
+
headers: {
|
|
19
|
+
'x-api-key': config.appSyncApiKey,
|
|
20
|
+
'x-scaly-api-key': config.scalyApiKey,
|
|
21
|
+
'Content-Type': 'application/json'
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return client;
|
|
25
|
+
}
|
|
26
|
+
function initOidcClient(config) {
|
|
27
|
+
if (!config.oidcToken)
|
|
28
|
+
return null;
|
|
29
|
+
oidcClient = new graphql_request_1.GraphQLClient(config.apiUrl, {
|
|
30
|
+
headers: {
|
|
31
|
+
// OIDC JWT auth for sensitive operations (DB/S3 execution tools)
|
|
32
|
+
authorization: `Bearer ${config.oidcToken}`,
|
|
33
|
+
// Keep AppSync key so the endpoint is reachable in all auth-mode configs
|
|
34
|
+
'x-api-key': config.appSyncApiKey,
|
|
35
|
+
'Content-Type': 'application/json'
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return oidcClient;
|
|
39
|
+
}
|
|
40
|
+
function getClient() {
|
|
41
|
+
if (!client) {
|
|
42
|
+
throw new Error('GraphQL client not initialized. Call initClient first.');
|
|
43
|
+
}
|
|
44
|
+
return client;
|
|
45
|
+
}
|
|
46
|
+
function getOidcClient() {
|
|
47
|
+
if (!oidcClient) {
|
|
48
|
+
throw new Error('OIDC client not initialized. Set SCALY_OIDC_TOKEN and restart the MCP server.');
|
|
49
|
+
}
|
|
50
|
+
return oidcClient;
|
|
51
|
+
}
|
|
52
|
+
// GraphQL query/mutation helpers
|
|
53
|
+
async function query(gql, variables) {
|
|
54
|
+
const c = getClient();
|
|
55
|
+
try {
|
|
56
|
+
return await c.request(gql, variables);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
// Extract meaningful error message
|
|
60
|
+
const message = error?.response?.errors?.[0]?.message ||
|
|
61
|
+
error?.message ||
|
|
62
|
+
'Unknown GraphQL error';
|
|
63
|
+
throw new Error(`Scaly API error: ${message}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function oidcQuery(gql, variables) {
|
|
67
|
+
const c = getOidcClient();
|
|
68
|
+
try {
|
|
69
|
+
return await c.request(gql, variables);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const message = error?.response?.errors?.[0]?.message ||
|
|
73
|
+
error?.message ||
|
|
74
|
+
'Unknown GraphQL error';
|
|
75
|
+
throw new Error(`Scaly API error: ${message}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Common GraphQL fragments - aligned with actual schema
|
|
79
|
+
exports.FRAGMENTS = {
|
|
80
|
+
app: `
|
|
81
|
+
fragment AppFields on App {
|
|
82
|
+
id
|
|
83
|
+
name
|
|
84
|
+
status
|
|
85
|
+
stackId
|
|
86
|
+
accountId
|
|
87
|
+
source
|
|
88
|
+
createdAt
|
|
89
|
+
updatedAt
|
|
90
|
+
}
|
|
91
|
+
`,
|
|
92
|
+
stack: `
|
|
93
|
+
fragment StackFields on Stack {
|
|
94
|
+
id
|
|
95
|
+
name
|
|
96
|
+
status
|
|
97
|
+
size
|
|
98
|
+
createdAt
|
|
99
|
+
updatedAt
|
|
100
|
+
}
|
|
101
|
+
`,
|
|
102
|
+
deployment: `
|
|
103
|
+
fragment DeploymentFields on Deployment {
|
|
104
|
+
id
|
|
105
|
+
status
|
|
106
|
+
resourceId
|
|
107
|
+
resourceType
|
|
108
|
+
createdAt
|
|
109
|
+
updatedAt
|
|
110
|
+
metadata
|
|
111
|
+
}
|
|
112
|
+
`,
|
|
113
|
+
scheduledJob: `
|
|
114
|
+
fragment ScheduledJobFields on ScheduledJob {
|
|
115
|
+
id
|
|
116
|
+
name
|
|
117
|
+
appId
|
|
118
|
+
command
|
|
119
|
+
schedule
|
|
120
|
+
timezone
|
|
121
|
+
status
|
|
122
|
+
lastRunAt
|
|
123
|
+
lastRunStatus
|
|
124
|
+
nextRunAt
|
|
125
|
+
createdAt
|
|
126
|
+
updatedAt
|
|
127
|
+
}
|
|
128
|
+
`,
|
|
129
|
+
jobRun: `
|
|
130
|
+
fragment JobRunFields on JobRun {
|
|
131
|
+
id
|
|
132
|
+
jobId
|
|
133
|
+
status
|
|
134
|
+
startedAt
|
|
135
|
+
finishedAt
|
|
136
|
+
exitCode
|
|
137
|
+
error
|
|
138
|
+
triggeredBy
|
|
139
|
+
}
|
|
140
|
+
`
|
|
141
|
+
};
|
|
142
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAMA,gCAYC;AAED,wCAYC;AAED,8BAKC;AAED,sCAOC;AAGD,sBAeC;AAED,8BAcC;AAlFD,qDAAgD;AAGhD,IAAI,MAAM,GAAyB,IAAI,CAAC;AACxC,IAAI,UAAU,GAAyB,IAAI,CAAC;AAE5C,SAAgB,UAAU,CAAC,MAAc;IACvC,gBAAgB;IAChB,oDAAoD;IACpD,qEAAqE;IACrE,MAAM,GAAG,IAAI,+BAAa,CAAC,MAAM,CAAC,MAAM,EAAE;QACxC,OAAO,EAAE;YACP,WAAW,EAAE,MAAM,CAAC,aAAa;YACjC,iBAAiB,EAAE,MAAM,CAAC,WAAW;YACrC,cAAc,EAAE,kBAAkB;SACnC;KACF,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,cAAc,CAAC,MAAc;IAC3C,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IACnC,UAAU,GAAG,IAAI,+BAAa,CAAC,MAAM,CAAC,MAAM,EAAE;QAC5C,OAAO,EAAE;YACP,iEAAiE;YACjE,aAAa,EAAE,UAAU,MAAM,CAAC,SAAS,EAAE;YAC3C,yEAAyE;YACzE,WAAW,EAAE,MAAM,CAAC,aAAa;YACjC,cAAc,EAAE,kBAAkB;SACnC;KACF,CAAC,CAAC;IACH,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAgB,SAAS;IACvB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,aAAa;IAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,+EAA+E,CAChF,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,iCAAiC;AAC1B,KAAK,UAAU,KAAK,CACzB,GAAW,EACX,SAAmC;IAEnC,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,CAAC,OAAO,CAAI,GAAG,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,mCAAmC;QACnC,MAAM,OAAO,GACX,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO;YACrC,KAAK,EAAE,OAAO;YACd,uBAAuB,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,SAAmC;IAEnC,MAAM,CAAC,GAAG,aAAa,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,CAAC,OAAO,CAAI,GAAG,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,MAAM,OAAO,GACX,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO;YACrC,KAAK,EAAE,OAAO;YACd,uBAAuB,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,wDAAwD;AAC3C,QAAA,SAAS,GAAG;IACvB,GAAG,EAAE;;;;;;;;;;;GAWJ;IACD,KAAK,EAAE;;;;;;;;;GASN;IACD,UAAU,EAAE;;;;;;;;;;GAUX;IACD,YAAY,EAAE;;;;;;;;;;;;;;;GAeb;IACD,MAAM,EAAE;;;;;;;;;;;GAWP;CACF,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const ConfigSchema: z.ZodObject<{
|
|
3
|
+
scalyApiKey: z.ZodString;
|
|
4
|
+
appSyncApiKey: z.ZodString;
|
|
5
|
+
oidcToken: z.ZodOptional<z.ZodString>;
|
|
6
|
+
apiUrl: z.ZodString;
|
|
7
|
+
stage: z.ZodOptional<z.ZodString>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
apiUrl: string;
|
|
10
|
+
scalyApiKey: string;
|
|
11
|
+
appSyncApiKey: string;
|
|
12
|
+
stage?: string | undefined;
|
|
13
|
+
oidcToken?: string | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
apiUrl: string;
|
|
16
|
+
scalyApiKey: string;
|
|
17
|
+
appSyncApiKey: string;
|
|
18
|
+
stage?: string | undefined;
|
|
19
|
+
oidcToken?: string | undefined;
|
|
20
|
+
}>;
|
|
21
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
22
|
+
export declare function loadConfig(): Config;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+BxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;EAMhB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,wBAAgB,UAAU,IAAI,MAAM,CAgDnC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadConfig = loadConfig;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
// Stage-aware configuration
|
|
6
|
+
// AppSync API keys enable API access; Scaly API keys provide authorization/scopes.
|
|
7
|
+
// The MCP AppSync keys are stage-wide and safe to ship as defaults; users can override with SCALY_APPSYNC_KEY.
|
|
8
|
+
const STAGE_CONFIG = {
|
|
9
|
+
prod: {
|
|
10
|
+
apiUrl: 'https://api.scalyapps.io/graphql',
|
|
11
|
+
defaultAppSyncApiKey: 'da2-2veyt7vqrbaqbjio56tcgpbboe'
|
|
12
|
+
},
|
|
13
|
+
dev: {
|
|
14
|
+
apiUrl: 'https://api.dev.scalyapps.io/graphql',
|
|
15
|
+
defaultAppSyncApiKey: 'da2-ujszvu6uwbenxfbtuy6svpffxi'
|
|
16
|
+
},
|
|
17
|
+
qa: {
|
|
18
|
+
apiUrl: 'https://api.qa.scalyapps.io/graphql',
|
|
19
|
+
defaultAppSyncApiKey: 'da2-riqkqxfjpjfihewbm4e2buq2xm'
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
function normalizeStage(stage) {
|
|
23
|
+
const s = (stage || '').trim().toLowerCase();
|
|
24
|
+
if (!s)
|
|
25
|
+
return 'prod';
|
|
26
|
+
if (s === 'production')
|
|
27
|
+
return 'prod';
|
|
28
|
+
if (s === 'staging')
|
|
29
|
+
return 'qa';
|
|
30
|
+
return s;
|
|
31
|
+
}
|
|
32
|
+
const ConfigSchema = zod_1.z.object({
|
|
33
|
+
scalyApiKey: zod_1.z.string().min(1, 'SCALY_API_KEY is required'),
|
|
34
|
+
appSyncApiKey: zod_1.z.string().min(1, 'SCALY_APPSYNC_KEY is required'),
|
|
35
|
+
oidcToken: zod_1.z.string().optional(),
|
|
36
|
+
apiUrl: zod_1.z.string().url(),
|
|
37
|
+
stage: zod_1.z.string().optional()
|
|
38
|
+
});
|
|
39
|
+
function loadConfig() {
|
|
40
|
+
const scalyApiKey = process.env.SCALY_API_KEY;
|
|
41
|
+
const oidcToken = process.env.SCALY_OIDC_TOKEN;
|
|
42
|
+
const apiUrl = process.env.SCALY_API_URL;
|
|
43
|
+
const stage = normalizeStage(process.env.SCALY_STAGE);
|
|
44
|
+
if (!scalyApiKey) {
|
|
45
|
+
console.error('Error: SCALY_API_KEY environment variable is required.\n\n' +
|
|
46
|
+
'Get your API key from: Scaly Dashboard → Account → Integrations → AI Assistant\n');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
// Determine API URL: explicit > stage-based > prod default
|
|
50
|
+
const stageConfig = STAGE_CONFIG[stage] || STAGE_CONFIG.prod;
|
|
51
|
+
const resolvedUrl = apiUrl || stageConfig.apiUrl;
|
|
52
|
+
const appSyncApiKey = process.env.SCALY_APPSYNC_KEY || stageConfig.defaultAppSyncApiKey;
|
|
53
|
+
if (!appSyncApiKey) {
|
|
54
|
+
console.error('Error: SCALY_APPSYNC_KEY environment variable is required.\n\n' +
|
|
55
|
+
'This is the stage-wide AppSync key for MCP access.\n' +
|
|
56
|
+
'If you are using the Scaly hosted environments (prod/dev/qa), you can omit SCALY_APPSYNC_KEY.\n');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const result = ConfigSchema.safeParse({
|
|
60
|
+
scalyApiKey,
|
|
61
|
+
appSyncApiKey,
|
|
62
|
+
oidcToken,
|
|
63
|
+
apiUrl: resolvedUrl,
|
|
64
|
+
stage
|
|
65
|
+
});
|
|
66
|
+
if (!result.success) {
|
|
67
|
+
console.error('Configuration error:', result.error.format());
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
// Log which endpoint we're using (helps with debugging)
|
|
71
|
+
if (stage !== 'prod') {
|
|
72
|
+
console.error(`Using ${stage} environment: ${resolvedUrl}`);
|
|
73
|
+
}
|
|
74
|
+
return result.data;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|