mc8yp 1.0.4 → 2.0.1
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 +188 -105
- package/dist/{add-BnID18hd.mjs → add-C-dXxz3k.mjs} +1 -4
- package/dist/cli.mjs +122515 -47111
- package/dist/creds-CpDDNTs5.mjs +18 -0
- package/dist/{list-qI93mmZ-.mjs → list-DZcNpiMS.mjs} +2 -5
- package/dist/{remove-B-bSxaTt.mjs → remove-DJHimlMb.mjs} +2 -5
- package/package.json +24 -17
- package/dist/creds-D4yS306d.mjs +0 -21
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|

|
|
5
5
|

|
|
6
6
|
|
|
7
|
-
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that
|
|
7
|
+
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that gives AI agents full access to the Cumulocity IoT platform through code execution. Instead of exposing dozens of fixed tools, the server provides two code-mode tools — `query` and `execute` — that let the agent write JavaScript to inspect the core OpenAPI spec and call any API endpoint.
|
|
8
8
|
|
|
9
9
|
**Two Deployment Modes:**
|
|
10
10
|
|
|
@@ -15,19 +15,16 @@ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that pr
|
|
|
15
15
|
|
|
16
16
|
### CLI Mode (Local Development & Testing)
|
|
17
17
|
|
|
18
|
-
The CLI mode allows you to run the MCP server locally and connect it to your AI agent (e.g., Claude Desktop). It uses STDIO transport and stores Cumulocity credentials securely in your system's native keyring.
|
|
19
|
-
|
|
20
18
|
```sh
|
|
21
|
-
# Run directly
|
|
19
|
+
# Run directly (recommended)
|
|
22
20
|
pnpm dlx mc8yp
|
|
23
21
|
|
|
22
|
+
# Pick a specific core OpenAPI snapshot for query
|
|
23
|
+
pnpm dlx mc8yp --spec 2025
|
|
24
|
+
|
|
24
25
|
# Or install globally
|
|
25
26
|
npm install -g mc8yp
|
|
26
27
|
mc8yp
|
|
27
|
-
|
|
28
|
-
# Or with pnpm
|
|
29
|
-
pnpm add -g mc8yp
|
|
30
|
-
mc8yp
|
|
31
28
|
```
|
|
32
29
|
|
|
33
30
|
**Credential Storage:**
|
|
@@ -39,22 +36,18 @@ Credentials are stored using your operating system's secure credential manager:
|
|
|
39
36
|
|
|
40
37
|
### Microservice Mode (Production Deployment)
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
**Deployment Steps:**
|
|
39
|
+
Designed **exclusively for deployment on Cumulocity IoT**. The server exposes an HTTP endpoint at `/mcp` that integrates with Cumulocity's agents manager, automatically using the service user's credentials and permissions.
|
|
45
40
|
|
|
46
41
|
1. Download the latest release package from [GitHub Releases](https://github.com/schplitt/mc8yp/releases)
|
|
47
|
-
2. Upload the `.zip`
|
|
42
|
+
2. Upload the `.zip` to Cumulocity via **Application Management**
|
|
48
43
|
3. Subscribe to the application in your tenant
|
|
49
44
|
4. The MCP server will be available at: `https://<tenant>.cumulocity.com/service/mc8yp-server/mcp`
|
|
50
45
|
|
|
51
|
-
|
|
46
|
+
No additional credential configuration needed — the microservice uses Cumulocity's built-in service user authentication.
|
|
52
47
|
|
|
53
48
|
## Usage
|
|
54
49
|
|
|
55
|
-
###
|
|
56
|
-
|
|
57
|
-
Before using the CLI, you need to store your Cumulocity credentials securely:
|
|
50
|
+
### Managing Credentials (CLI)
|
|
58
51
|
|
|
59
52
|
```sh
|
|
60
53
|
# Add credentials (prompts for tenant URL, username, password)
|
|
@@ -67,11 +60,28 @@ pnpm dlx mc8yp creds list
|
|
|
67
60
|
pnpm dlx mc8yp creds remove
|
|
68
61
|
```
|
|
69
62
|
|
|
70
|
-
|
|
63
|
+
### Selecting The Core OpenAPI Snapshot (CLI)
|
|
64
|
+
|
|
65
|
+
Use `--spec` or `-s` to choose which bundled core OpenAPI snapshot the `query` tool exposes.
|
|
71
66
|
|
|
72
|
-
|
|
67
|
+
Supported values are `release`, `2026`, `2025`, and `2024`.
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
# Default: latest bundled release snapshot
|
|
71
|
+
mc8yp
|
|
72
|
+
|
|
73
|
+
# Explicitly use the 2025 core OpenAPI snapshot
|
|
74
|
+
mc8yp --spec 2025
|
|
75
|
+
|
|
76
|
+
# Short form
|
|
77
|
+
mc8yp -s 2024
|
|
78
|
+
```
|
|
73
79
|
|
|
74
|
-
|
|
80
|
+
This only affects the `query` tool's OpenAPI view. The `execute` tool still calls the live Cumulocity API of the selected tenant or deployed service environment.
|
|
81
|
+
|
|
82
|
+
### Connecting to AI Agents
|
|
83
|
+
|
|
84
|
+
For Claude Desktop or any MCP client, add to your MCP configuration:
|
|
75
85
|
|
|
76
86
|
```json
|
|
77
87
|
{
|
|
@@ -85,136 +95,209 @@ For local development with Claude Desktop or similar MCP clients, add to your MC
|
|
|
85
95
|
}
|
|
86
96
|
```
|
|
87
97
|
|
|
88
|
-
|
|
98
|
+
With restrictions (see [API Restrictions](#api-restrictions)):
|
|
89
99
|
|
|
90
|
-
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"servers": {
|
|
103
|
+
"mc8yp": {
|
|
104
|
+
"type": "stdio",
|
|
105
|
+
"command": "pnpm",
|
|
106
|
+
"args": ["dlx", "mc8yp", "-r", "/alarm/**", "-r", "DELETE:/inventory/**"]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
91
111
|
|
|
92
|
-
|
|
112
|
+
## Tools & Prompts
|
|
93
113
|
|
|
94
|
-
|
|
95
|
-
- pnpm
|
|
96
|
-
- Access to a Cumulocity IoT tenant
|
|
114
|
+
### Tools
|
|
97
115
|
|
|
98
|
-
|
|
116
|
+
| Tool | Description |
|
|
117
|
+
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
118
|
+
| `query` | Search and inspect the bundled Cumulocity core OpenAPI spec by running a JavaScript module. The spec is injected as a top-level `spec` binding. Export the result with `export default`. |
|
|
119
|
+
| `execute` | Execute JavaScript against the live Cumulocity API. Provide an async JavaScript function expression. A top-level `cumulocity` binding provides `cumulocity.request({ method, path, body?, headers? })`. Return the final value from that function. |
|
|
120
|
+
| `list-credentials` | _(CLI mode only)_ List stored credentials from your system keyring. |
|
|
99
121
|
|
|
100
|
-
|
|
101
|
-
# Install dependencies
|
|
102
|
-
pnpm install
|
|
122
|
+
Both code-mode tools run in a sandboxed runtime ([secure-exec](https://github.com/nicepkg/secure-exec)).
|
|
103
123
|
|
|
104
|
-
|
|
105
|
-
|
|
124
|
+
- `query` returns JSON text for easier inspection of OpenAPI data.
|
|
125
|
+
- `execute` returns the successful function result in [Toon format](https://github.com/nicepkg/toon). If execution is blocked or fails, it returns a plain text message instead.
|
|
106
126
|
|
|
107
|
-
|
|
108
|
-
pnpm typecheck
|
|
127
|
+
### Execute Input Shape
|
|
109
128
|
|
|
110
|
-
|
|
111
|
-
|
|
129
|
+
The `execute` tool expects an async function expression, not module source with `export default`.
|
|
130
|
+
|
|
131
|
+
Recommended shape:
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
async () => {
|
|
135
|
+
return await cumulocity.request({
|
|
136
|
+
method: 'GET',
|
|
137
|
+
path: '/inventory/managedObjects?pageSize=5',
|
|
138
|
+
})
|
|
139
|
+
}
|
|
112
140
|
```
|
|
113
141
|
|
|
114
|
-
|
|
142
|
+
You can also perform intermediate processing before returning the final value:
|
|
115
143
|
|
|
116
|
-
|
|
144
|
+
```js
|
|
145
|
+
async () => {
|
|
146
|
+
const devices = await cumulocity.request({
|
|
147
|
+
method: 'GET',
|
|
148
|
+
path: '/inventory/managedObjects?pageSize=20&withTotalPages=true',
|
|
149
|
+
})
|
|
117
150
|
|
|
118
|
-
|
|
119
|
-
{
|
|
120
|
-
"servers": {
|
|
121
|
-
"local_mc8yp": {
|
|
122
|
-
"type": "stdio",
|
|
123
|
-
"command": "pnpm",
|
|
124
|
-
"args": [
|
|
125
|
-
"dlx",
|
|
126
|
-
"jiti",
|
|
127
|
-
"/path/to/your/project/src/cli/index.ts"
|
|
128
|
-
]
|
|
129
|
-
}
|
|
130
|
-
}
|
|
151
|
+
return devices.managedObjects?.map((device) => ({ id: device.id, name: device.name }))
|
|
131
152
|
}
|
|
132
153
|
```
|
|
133
154
|
|
|
134
|
-
|
|
155
|
+
### Prompts
|
|
156
|
+
|
|
157
|
+
| Prompt | Description |
|
|
158
|
+
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
159
|
+
| `code-mode-guide` | Full reference for the `query` and `execute` tools, including available types, examples, and restriction info for the current connection. |
|
|
160
|
+
|
|
161
|
+
## API Restrictions
|
|
162
|
+
|
|
163
|
+
Restrictions are deny rules that block specific API operations. They can be applied per-connection to limit what an AI agent can access.
|
|
164
|
+
|
|
165
|
+
### Rule Format
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
[METHOD:]<path-pattern>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- **Without a method prefix** — blocks all HTTP methods for matching paths
|
|
172
|
+
- **With a method prefix** — blocks only that method (e.g. `GET:`, `DELETE:`, `POST:`)
|
|
173
|
+
- **Path patterns** support `*` (single segment wildcard) and `**` (recursive wildcard)
|
|
174
|
+
- Query strings and fragments are not allowed in patterns
|
|
135
175
|
|
|
136
|
-
|
|
176
|
+
### Examples
|
|
137
177
|
|
|
138
|
-
|
|
178
|
+
| Rule | Effect |
|
|
179
|
+
| -------------------------------- | --------------------------------------------------- |
|
|
180
|
+
| `/inventory/**` | Block all methods on all inventory paths |
|
|
181
|
+
| `DELETE:/inventory/**` | Block only DELETE on inventory paths |
|
|
182
|
+
| `/alarm/alarms` | Block all methods on the exact path `/alarm/alarms` |
|
|
183
|
+
| `GET:/measurement/measurements` | Block only GET on measurements |
|
|
184
|
+
| `POST:/inventory/managedObjects` | Block creating new managed objects |
|
|
185
|
+
| `/user/**` | Block all user management |
|
|
139
186
|
|
|
140
|
-
|
|
187
|
+
### CLI Mode
|
|
141
188
|
|
|
142
|
-
|
|
189
|
+
Pass restrictions as CLI arguments. Repeat `-r` / `--restriction` for multiple rules:
|
|
143
190
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
- `get-supported-series` - Discover measurement types a device supports
|
|
191
|
+
```sh
|
|
192
|
+
# Block all inventory access
|
|
193
|
+
mc8yp -r "/inventory/**"
|
|
148
194
|
|
|
149
|
-
|
|
195
|
+
# Block deletes on inventory and all alarm access
|
|
196
|
+
mc8yp -r "DELETE:/inventory/**" -r "/alarm/**"
|
|
150
197
|
|
|
151
|
-
|
|
152
|
-
|
|
198
|
+
# Block everything under user management
|
|
199
|
+
mc8yp --restriction "/user/**"
|
|
200
|
+
```
|
|
153
201
|
|
|
154
|
-
|
|
202
|
+
### Microservice Mode (HTTP)
|
|
155
203
|
|
|
156
|
-
|
|
157
|
-
- `get-event-types` - Discover available event types for a device
|
|
204
|
+
Pass restrictions as `restriction` query parameters on the MCP endpoint URL:
|
|
158
205
|
|
|
159
|
-
|
|
206
|
+
```
|
|
207
|
+
/mcp?restriction=/inventory/**&restriction=DELETE:/alarm/**
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### How Restrictions Work
|
|
160
211
|
|
|
161
|
-
|
|
162
|
-
- `get-alarm-counts` - Get alarm counts grouped by severity
|
|
212
|
+
1. **OpenAPI spec annotation**: The `query` tool annotates blocked operations in the spec with `x-mc8yp-restricted` and related `x-mc8yp-*` metadata fields. The operations remain visible so the agent understands what exists, but they are clearly marked as blocked.
|
|
163
213
|
|
|
164
|
-
**
|
|
214
|
+
2. **Sandbox request enforcement**: The `execute` tool checks restrictions inside the generated sandbox request helper, where the actual HTTP method and normalized path are both available. Matching requests are blocked before any `fetch` is attempted.
|
|
165
215
|
|
|
166
|
-
|
|
167
|
-
- `get-current-user` - Get current user details
|
|
168
|
-
- `get-users` - List users on the tenant
|
|
169
|
-
- `get-applications` - List available applications
|
|
170
|
-
- `get-application` - Get specific application details
|
|
171
|
-
- `get-application-versions` - Get all versions of an application
|
|
172
|
-
- `get-audit` - Query audit logs
|
|
173
|
-
- `get-tenant-stats` - Get tenant usage statistics
|
|
174
|
-
- `get-tenant-summary` - Get tenant usage summary
|
|
175
|
-
- `get-dashboards` - Get dashboards for a device or group
|
|
216
|
+
3. **Network boundary**: The secure-exec permission layer independently restricts network access to the configured tenant host. Other network operations are denied.
|
|
176
217
|
|
|
177
|
-
|
|
218
|
+
When an `execute` request is blocked by MCP restrictions, the tool returns explanatory text stating that the operation was intentionally denied by MCP connection policy, no request was sent to Cumulocity, and retrying through the same connection will not help.
|
|
178
219
|
|
|
179
|
-
|
|
220
|
+
## Build And Packaging
|
|
180
221
|
|
|
181
|
-
|
|
222
|
+
The repository bundles multiple core OpenAPI snapshots for CLI use and builds one microservice server bundle per snapshot version.
|
|
182
223
|
|
|
183
|
-
|
|
184
|
-
- Time window guidance for queries
|
|
224
|
+
### Build Outputs
|
|
185
225
|
|
|
186
|
-
|
|
226
|
+
`pnpm build` produces:
|
|
187
227
|
|
|
188
|
-
-
|
|
189
|
-
-
|
|
190
|
-
- OData query syntax help
|
|
191
|
-
- Device discovery workflows
|
|
228
|
+
- CLI bundle in `dist/`
|
|
229
|
+
- Versioned server bundles in `.output/release/`, `.output/2026/`, `.output/2025/`, and `.output/2024/`
|
|
192
230
|
|
|
193
|
-
|
|
231
|
+
The versions built are driven by [`openapi-versions.json`](openapi-versions.json). Each server bundle contains only its own `core-openapi/<version>.json` snapshot.
|
|
194
232
|
|
|
195
|
-
|
|
196
|
-
- Time range calculations
|
|
197
|
-
- Data aggregation guidance
|
|
233
|
+
### Release Packaging
|
|
198
234
|
|
|
199
|
-
|
|
235
|
+
Use the dedicated packaging command after `pnpm build` to create Docker-based Cumulocity release zips:
|
|
200
236
|
|
|
201
|
-
-
|
|
202
|
-
- Event history querying
|
|
237
|
+
The packaging step writes a temporary generated Dockerfile under `.c8y/`, copies the selected versioned server bundle into `/app/server/`, and installs production dependencies inside the Linux image with pnpm before copying them into the runtime stage. This avoids cross-platform native optional dependency issues when release artifacts are built on macOS but deployed as `linux/amd64` microservices.
|
|
203
238
|
|
|
204
|
-
|
|
239
|
+
The deployed HTTP transport uses POST-only streamable HTTP (`GET /mcp` intentionally returns `405`) because some reverse proxies and microservice ingress layers do not keep the optional long-lived SSE notification channel stable enough for reliable MCP tool calls.
|
|
205
240
|
|
|
206
|
-
|
|
207
|
-
|
|
241
|
+
```sh
|
|
242
|
+
pnpm package:microservices
|
|
243
|
+
```
|
|
208
244
|
|
|
209
|
-
|
|
245
|
+
That command creates one zip per bundled server variant in the repository root, for example:
|
|
210
246
|
|
|
211
|
-
-
|
|
247
|
+
- `mc8yp-release-v1.2.3.zip`
|
|
248
|
+
- `mc8yp-2026-v1.2.3.zip`
|
|
249
|
+
- `mc8yp-2025-v1.2.3.zip`
|
|
250
|
+
- `mc8yp-2024-v1.2.3.zip`
|
|
212
251
|
|
|
213
|
-
|
|
252
|
+
The GitHub release workflow uses that packaging command when building tagged releases.
|
|
214
253
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
254
|
+
## Development
|
|
255
|
+
|
|
256
|
+
### Prerequisites
|
|
257
|
+
|
|
258
|
+
- Node.js ≥24.0.0
|
|
259
|
+
- pnpm
|
|
260
|
+
|
|
261
|
+
### Setup
|
|
262
|
+
|
|
263
|
+
```sh
|
|
264
|
+
pnpm install
|
|
265
|
+
pnpm lint
|
|
266
|
+
pnpm typecheck
|
|
267
|
+
pnpm build
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Testing
|
|
271
|
+
|
|
272
|
+
```sh
|
|
273
|
+
# Run tests
|
|
274
|
+
pnpm test:run
|
|
275
|
+
|
|
276
|
+
# Run benchmarks
|
|
277
|
+
pnpm test:bench
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Run Locally
|
|
281
|
+
|
|
282
|
+
Build first, then point your MCP client at the compiled CLI:
|
|
283
|
+
|
|
284
|
+
```sh
|
|
285
|
+
pnpm build
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Then add to your local MCP client configuration:
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"servers": {
|
|
293
|
+
"local_mc8yp": {
|
|
294
|
+
"type": "stdio",
|
|
295
|
+
"command": "node",
|
|
296
|
+
"args": ["/path/to/your/project/dist/cli.mjs"]
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
218
301
|
|
|
219
302
|
## License
|
|
220
303
|
|
|
@@ -3,7 +3,6 @@ import { defineCommand } from "citty";
|
|
|
3
3
|
import consola from "consola";
|
|
4
4
|
import * as v from "valibot";
|
|
5
5
|
import { exit } from "node:process";
|
|
6
|
-
|
|
7
6
|
//#region src/cli/subcommands/subcommands/add.ts
|
|
8
7
|
const command = defineCommand({
|
|
9
8
|
meta: {
|
|
@@ -47,7 +46,5 @@ const command = defineCommand({
|
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
});
|
|
50
|
-
var add_default = command;
|
|
51
|
-
|
|
52
49
|
//#endregion
|
|
53
|
-
export {
|
|
50
|
+
export { command as default };
|