@uptimizr/mcp 1.0.1 → 1.1.0
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/AGENTS.md +49 -7
- package/README.md +93 -27
- package/dist/capabilities.d.ts +62 -5
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +59 -33
- package/dist/capabilities.js.map +1 -1
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +48 -1
- package/dist/server.js.map +1 -1
- package/llms.txt +25 -1
- package/package.json +4 -3
package/AGENTS.md
CHANGED
|
@@ -21,10 +21,48 @@ UPTIMIZR_COLLECTOR_URL="https://collect.example.com" UPTIMIZR_API_KEY="utk_…"
|
|
|
21
21
|
|
|
22
22
|
## Tools (read-only)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
`
|
|
27
|
-
|
|
24
|
+
<!-- generated:registry-tool-names:start — generated by `pnpm gen:docs`; edit the metric registry, not this table -->
|
|
25
|
+
|
|
26
|
+
`list_sessions`, `session_meta`, `scene_representation`, `list_scenes`, `timeseries`,
|
|
27
|
+
`event_counts`, `pointer_heatmap`, `mesh_uv_heatmap`, `world_heatmap`, `world_heatmap_stats`,
|
|
28
|
+
`gaze_heatmap`, `gaze_heatmap_stats`, `camera_heatmap`, `view_coverage_histogram`,
|
|
29
|
+
`position_heatmap`, `session_trajectory`, `aggregate_paths`, `scene_coverage`, `camera_distance`,
|
|
30
|
+
`click_rays`, `flow_links`, `top_meshes`, `mesh_sources`, `mesh_trend`, `mesh_dwell`,
|
|
31
|
+
`mesh_blind_spots`, `mesh_interaction_kinds`, `mesh_reachability`, `dead_clicks`, `rage_clicks`,
|
|
32
|
+
`hover_dwell`, `interaction_sources`, `top_input_actions`, `camera_gestures`, `navigation_stats`,
|
|
33
|
+
`backtrack_ratio`, `perf_summary`, `render_scale_truth`, `perf_distribution`, `fps_histogram`,
|
|
34
|
+
`frame_time_percentiles`, `jank_rate`, `perf_churn`, `perf_by_device`, `perf_by_scene`,
|
|
35
|
+
`perf_heatmap`, `compile_stalls`, `resource_summary`, `resource_percentiles`, `stability_counts`,
|
|
36
|
+
`graphics_diagnostics`, `error_heatmap`, `rendering_technology`, `capability_changes`,
|
|
37
|
+
`xr_rotation`, `xr_sources`, `xr_abandonment`, `xr_locomotion`, `xr_tracking_quality`,
|
|
38
|
+
`boundary_heatmap`, `boundary_heatmap_stats`, `xr_boundary_contacts`,
|
|
39
|
+
`ar_placement_time_to_place`, `ar_placement_attempts`, `ar_placement_surfaces`, `funnel`,
|
|
40
|
+
`scene_retention`, `load_bounce_funnel`, `variant_leaderboard`
|
|
41
|
+
|
|
42
|
+
<!-- generated:registry-tool-names:end -->
|
|
43
|
+
|
|
44
|
+
**69 tools, generated** from the `@uptimizr/metrics` semantic metric registry (ADR 0051 §1) — one per
|
|
45
|
+
metric the collector serves on a read endpoint. Names are the registry ids; the full table lives in
|
|
46
|
+
[README.md](./README.md), and `uptimizr://capabilities` enumerates them at runtime with each tool's
|
|
47
|
+
grain, column units and caveats.
|
|
48
|
+
|
|
49
|
+
Orientation: `list_sessions`, `list_scenes`, `session_meta`, `scene_representation`, `timeseries`,
|
|
50
|
+
`event_counts`. Attention: the `*_heatmap` family, `mesh_dwell`, `mesh_blind_spots`, `hover_dwell`.
|
|
51
|
+
Interaction: `top_meshes`, `mesh_sources`, `mesh_trend`, `mesh_interaction_kinds`,
|
|
52
|
+
`mesh_reachability`, `dead_clicks`, `rage_clicks`, `interaction_sources`, `top_input_actions`.
|
|
53
|
+
Navigation: `aggregate_paths`, `session_trajectory`, `scene_coverage`, `navigation_stats`,
|
|
54
|
+
`backtrack_ratio`, `camera_distance`, `camera_gestures`. Performance: `perf_summary`, `jank_rate`,
|
|
55
|
+
`perf_by_device`, `perf_by_scene`, `perf_heatmap`, `fps_histogram`, `frame_time_percentiles`,
|
|
56
|
+
`compile_stalls`, `resource_summary`, `rendering_technology`, … Errors: `stability_counts`,
|
|
57
|
+
`graphics_diagnostics`, `error_heatmap`, `capability_changes`. XR/AR: the `xr_*` and
|
|
58
|
+
`ar_placement_*` families. Conversion: `funnel`, `scene_retention`, `load_bounce_funnel`,
|
|
59
|
+
`variant_leaderboard`.
|
|
60
|
+
|
|
61
|
+
Most accept `since`/`until` (epoch ms) plus endpoint-specific filters (`scene`, `session`, `source`,
|
|
62
|
+
`bins`, `cellSize`, `limit`, `cameraMode`, `region`, …). Every tool declares an `outputSchema` and
|
|
63
|
+
returns `structuredContent` (`{ rows }`) alongside the JSON text — read the schema instead of
|
|
64
|
+
guessing the row shape, and read the tool description for the metric's caveats before trusting a
|
|
65
|
+
small sample.
|
|
28
66
|
|
|
29
67
|
## Rules for agents
|
|
30
68
|
|
|
@@ -32,9 +70,13 @@ UPTIMIZR_COLLECTOR_URL="https://collect.example.com" UPTIMIZR_API_KEY="utk_…"
|
|
|
32
70
|
tools here. No data leaves the consumer's infrastructure (ADR 0003).
|
|
33
71
|
- The server talks only to the configured collector with the consumer's `x-api-key`; never hardcode
|
|
34
72
|
or log credentials.
|
|
35
|
-
- Keep it a thin wrapper:
|
|
36
|
-
`@uptimizr/
|
|
37
|
-
|
|
73
|
+
- Keep it a thin wrapper: the `readTools` catalog (defined in `@uptimizr/agent-core`) is
|
|
74
|
+
**generated** from the `@uptimizr/metrics` metric registry, so a new tool = a new registry entry
|
|
75
|
+
for a documented query endpoint — never a hand-written array entry here. Do not add
|
|
76
|
+
aggregation/business logic — that lives in the collector.
|
|
77
|
+
- **No database driver, ever.** This server talks to a collector over HTTP; it must stay installable
|
|
78
|
+
with `npx`. Never add `@uptimizr/db` (or any package with a native/optional binary dependency) to
|
|
79
|
+
`dependencies` — `src/__tests__/dependencies.test.ts` fails if you do.
|
|
38
80
|
- Tool definitions are pure (`buildRequest`) and must stay unit-testable without a live collector.
|
|
39
81
|
|
|
40
82
|
## Programmatic API
|
package/README.md
CHANGED
|
@@ -75,37 +75,103 @@ For **GitHub Copilot CLI**, put the same entry in `~/.copilot/mcp-config.json` w
|
|
|
75
75
|
|
|
76
76
|
## Tools
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
the
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
|
96
|
-
|
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
78
|
+
The catalog is **generated from the semantic metric registry** in `@uptimizr/metrics` (ADR 0051 §1):
|
|
79
|
+
every aggregation the collector serves on a read endpoint is a tool — **69** of them. Each tool's
|
|
80
|
+
description carries the metric's interpretation notes and caveats, and each declares an MCP
|
|
81
|
+
`outputSchema` for the rows it returns (results come back as both `content` text and
|
|
82
|
+
`structuredContent`).
|
|
83
|
+
|
|
84
|
+
The table is **generated** from the collector's semantic metric registry (ADR 0051) — one row per
|
|
85
|
+
registered read metric. Read `uptimizr://capabilities` for each one's result grain, column units,
|
|
86
|
+
row schema and caveats; the same registry drives the collector's `GET /api/v1/openapi.json`.
|
|
87
|
+
|
|
88
|
+
Most tools accept an optional time range (`since` / `until`, epoch ms) and the filters the
|
|
89
|
+
underlying endpoint supports (`scene`, `session`, `source`, `bins`, `cellSize`, `interval`, `type`,
|
|
90
|
+
`limit`, `cameraMode`, `region`, …). `session_meta`, `session_trajectory` and
|
|
91
|
+
`scene_representation` take a required id.
|
|
92
|
+
|
|
93
|
+
<!-- generated:registry-tools:start — generated by `pnpm gen:docs`; edit the metric registry, not this table -->
|
|
94
|
+
|
|
95
|
+
| Tool | Endpoint | Returns | Parameters |
|
|
96
|
+
| ---------------------------- | ---------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
97
|
+
| `list_sessions` | `/api/v1/sessions` | Recent sessions | `since`, `until`, `bins`, `limit`, `cameraMode`, `format` |
|
|
98
|
+
| `session_meta` | `/api/v1/sessions/:id/meta` | Session descriptor | `session` |
|
|
99
|
+
| `scene_representation` | `/api/v1/scenes/:sceneId/representation` | Scene representation | `scene` |
|
|
100
|
+
| `list_scenes` | `/api/v1/scenes` | Active scenes | `since`, `until`, `limit`, `format` |
|
|
101
|
+
| `timeseries` | `/api/v1/timeseries` | Event volume over time | `since`, `until`, `interval`, `scene`, `type`, `format` |
|
|
102
|
+
| `event_counts` | `/api/v1/event-counts` | Counts per event type | `since`, `until`, `scene`, `format` |
|
|
103
|
+
| `pointer_heatmap` | `/api/v1/heatmaps/pointer` | 2D pointer heatmap | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `format` |
|
|
104
|
+
| `mesh_uv_heatmap` | `/api/v1/heatmaps/mesh-uv` | Per-mesh UV (texture-space) heatmap | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `mesh`, `format` |
|
|
105
|
+
| `world_heatmap` | `/api/v1/heatmaps/world` | 3D world-space pointer heatmap | `since`, `until`, `cellSize`, `limit`, `scene`, `source`, `cameraMode`, `region`, `format` |
|
|
106
|
+
| `world_heatmap_stats` | `/api/v1/heatmaps/world/stats` | World heatmap totals | `since`, `until`, `cellSize`, `scene`, `source`, `cameraMode`, `region`, `format` |
|
|
107
|
+
| `gaze_heatmap` | `/api/v1/heatmaps/gaze` | World-space gaze heatmap | `since`, `until`, `cellSize`, `limit`, `scene`, `session`, `cameraMode`, `region`, `format` |
|
|
108
|
+
| `gaze_heatmap_stats` | `/api/v1/heatmaps/gaze/stats` | Gaze heatmap totals | `since`, `until`, `cellSize`, `scene`, `session`, `cameraMode`, `region`, `format` |
|
|
109
|
+
| `camera_heatmap` | `/api/v1/heatmaps/camera` | View-direction heatmap | `since`, `until`, `bins`, `limit`, `scene`, `session`, `cameraMode`, `format` |
|
|
110
|
+
| `view_coverage_histogram` | `/api/v1/coverage/view-histogram` | 360° view-coverage histogram | `since`, `until`, `bins`, `limit`, `scene`, `session`, `cameraMode`, `format` |
|
|
111
|
+
| `position_heatmap` | `/api/v1/heatmaps/position` | Floor-plan camera-position heatmap | `since`, `until`, `cellSize`, `limit`, `scene`, `session`, `cameraMode`, `region`, `format` |
|
|
112
|
+
| `session_trajectory` | `/api/v1/sessions/:sessionId/trajectory` | Session walked path | `session`, `since`, `until`, `limit`, `scene`, `format` |
|
|
113
|
+
| `aggregate_paths` | `/api/v1/paths` | Aggregate desire-line paths | `since`, `until`, `cellSize`, `limit`, `scene`, `cameraMode`, `format` |
|
|
114
|
+
| `scene_coverage` | `/api/v1/coverage` | Scene coverage / dead zones | `since`, `until`, `cellSize`, `limit`, `scene`, `session`, `format` |
|
|
115
|
+
| `camera_distance` | `/api/v1/camera/distance` | Camera distance / zoom distribution | `since`, `until`, `centerX`, `centerY`, `centerZ`, `bucketSize`, `limit`, `scene`, `session`, `format` |
|
|
116
|
+
| `click_rays` | `/api/v1/heatmaps/click-rays` | View-gated click rays | `since`, `until`, `cellSize`, `limit`, `scene`, `source`, `session`, `format` |
|
|
117
|
+
| `flow_links` | `/api/v1/heatmaps/flow` | Gaze → mesh flow links | `since`, `until`, `bins`, `limit`, `scene`, `session`, `cameraMode`, `cellSize`, `groupByOrigin`, `originVoxel`, `format` |
|
|
118
|
+
| `top_meshes` | `/api/v1/meshes/top` | Most-interacted meshes | `since`, `until`, `bins`, `limit`, `session`, `format` |
|
|
119
|
+
| `mesh_sources` | `/api/v1/meshes/sources` | Mesh interactions by input source | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `format` |
|
|
120
|
+
| `mesh_trend` | `/api/v1/meshes/trend` | Per-mesh interaction trend | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `interval`, `format` |
|
|
121
|
+
| `mesh_dwell` | `/api/v1/meshes/dwell` | Per-object dwell / attention | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
122
|
+
| `mesh_blind_spots` | `/api/v1/meshes/blind-spots` | Blind spots / never-noticed meshes | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
123
|
+
| `mesh_interaction_kinds` | `/api/v1/meshes/kinds` | Interaction kinds per mesh | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `format` |
|
|
124
|
+
| `mesh_reachability` | `/api/v1/meshes/reachability` | Mesh reachability by distance | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `bucketSize`, `format` |
|
|
125
|
+
| `dead_clicks` | `/api/v1/clicks/dead` | Dead-click rate | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `format` |
|
|
126
|
+
| `rage_clicks` | `/api/v1/clicks/rage` | Rage-click clusters | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `interval`, `minRepeats`, `format` |
|
|
127
|
+
| `hover_dwell` | `/api/v1/hover/dwell` | Hover hesitation per object | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `format` |
|
|
128
|
+
| `interaction_sources` | `/api/v1/interactions/sources` | Interactions by input source | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `format` |
|
|
129
|
+
| `top_input_actions` | `/api/v1/input-actions/top` | Most-used shortcuts and actions | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `format` |
|
|
130
|
+
| `camera_gestures` | `/api/v1/camera-gestures` | Camera navigation gestures | `since`, `until`, `bins`, `limit`, `scene`, `session`, `source`, `cameraMode`, `format` |
|
|
131
|
+
| `navigation_stats` | `/api/v1/navigation` | Navigation effort per session | `since`, `until`, `moveThreshold`, `limit`, `scene`, `session`, `format` |
|
|
132
|
+
| `backtrack_ratio` | `/api/v1/backtrack` | Path retrace / backtracking | `since`, `until`, `cellSize`, `limit`, `scene`, `session`, `format` |
|
|
133
|
+
| `perf_summary` | `/api/v1/perf` | Rendering performance summary | `since`, `until`, `bins`, `limit`, `session`, `format` |
|
|
134
|
+
| `render_scale_truth` | `/api/v1/perf/render-scale` | Render-scale truth | `since`, `until`, `bins`, `limit`, `session`, `format` |
|
|
135
|
+
| `perf_distribution` | `/api/v1/perf/distribution` | FPS distribution (per-session) | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
136
|
+
| `fps_histogram` | `/api/v1/perf/fps-histogram` | Per-session median-FPS histogram | `since`, `until`, `bins`, `limit`, `scene`, `session`, `bucket`, `format` |
|
|
137
|
+
| `frame_time_percentiles` | `/api/v1/perf/frame-time` | Frame-time percentiles | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
138
|
+
| `jank_rate` | `/api/v1/perf/jank` | Jank rate | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
139
|
+
| `perf_churn` | `/api/v1/perf/churn` | Perf-correlated churn | `since`, `until`, `bins`, `limit`, `scene`, `session`, `windowMs`, `fpsThreshold`, `stallMs`, `format` |
|
|
140
|
+
| `perf_by_device` | `/api/v1/perf/by-device` | FPS by device class | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
141
|
+
| `perf_by_scene` | `/api/v1/perf/by-scene` | FPS by scene | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
142
|
+
| `perf_heatmap` | `/api/v1/heatmaps/perf` | Spatial FPS heatmap | `since`, `until`, `cellSize`, `limit`, `scene`, `session`, `format` |
|
|
143
|
+
| `compile_stalls` | `/api/v1/perf/compile-stalls` | Shader / pipeline compile stalls | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
144
|
+
| `resource_summary` | `/api/v1/perf/resources` | GPU / memory footprint summary | `since`, `until`, `bins`, `limit`, `session`, `format` |
|
|
145
|
+
| `resource_percentiles` | `/api/v1/perf/resource-percentiles` | GPU / memory footprint percentiles | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
146
|
+
| `stability_counts` | `/api/v1/perf/stability` | Stability incidents | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
147
|
+
| `graphics_diagnostics` | `/api/v1/graphics-diagnostics` | Engine diagnostic counts | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
148
|
+
| `error_heatmap` | `/api/v1/heatmaps/errors` | Spatial error heatmap | `since`, `until`, `cellSize`, `limit`, `scene`, `session`, `region`, `severity`, `category`, `errorKind`, `format` |
|
|
149
|
+
| `rendering_technology` | `/api/v1/rendering-technology` | Rendering-technology mix | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
150
|
+
| `capability_changes` | `/api/v1/capabilities` | Capability / fidelity transitions | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
151
|
+
| `xr_rotation` | `/api/v1/xr/rotation` | XR head-rotation rate | `since`, `until`, `rapidTurn`, `limit`, `scene`, `session`, `format` |
|
|
152
|
+
| `xr_sources` | `/api/v1/xr/sources` | XR input-source usage | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
153
|
+
| `xr_abandonment` | `/api/v1/xr/abandonment` | XR session abandonment | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
154
|
+
| `xr_locomotion` | `/api/v1/xr/locomotion` | XR locomotion & comfort | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
155
|
+
| `xr_tracking_quality` | `/api/v1/xr/tracking` | XR tracking quality | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
156
|
+
| `boundary_heatmap` | `/api/v1/heatmaps/boundary` | Guardian / boundary-touch heatmap | `since`, `until`, `cellSize`, `limit`, `scene`, `session`, `region`, `format` |
|
|
157
|
+
| `boundary_heatmap_stats` | `/api/v1/heatmaps/boundary/stats` | Boundary heatmap totals | `since`, `until`, `cellSize`, `scene`, `session`, `region`, `format` |
|
|
158
|
+
| `xr_boundary_contacts` | `/api/v1/xr/boundary-contacts` | Boundary contacts per session | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
159
|
+
| `ar_placement_time_to_place` | `/api/v1/ar/placement/time-to-place` | AR time-to-place distribution | `since`, `until`, `bins`, `limit`, `scene`, `session`, `bucketMs`, `format` |
|
|
160
|
+
| `ar_placement_attempts` | `/api/v1/ar/placement/attempts` | AR re-placement distribution | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
161
|
+
| `ar_placement_surfaces` | `/api/v1/ar/placement/surfaces` | AR placement surfaces | `since`, `until`, `bins`, `limit`, `scene`, `session`, `format` |
|
|
162
|
+
| `funnel` | `/api/v1/funnel` | Conversion funnel | `since`, `until`, `scene`, `cameraMode`, `steps`, `format` |
|
|
163
|
+
| `scene_retention` | `/api/v1/scene-retention` | Scene-to-scene retention | `since`, `until`, `limit`, `format` |
|
|
164
|
+
| `load_bounce_funnel` | `/api/v1/load-bounce` | Load → bounce funnel | `since`, `until`, `scene`, `bands`, `format` |
|
|
165
|
+
| `variant_leaderboard` | `/api/v1/variant-leaderboard` | Variant → conversion leaderboard | `since`, `until`, `scene`, `cameraMode`, `variant`, `conversion`, `limit`, `format` |
|
|
166
|
+
|
|
167
|
+
<!-- generated:registry-tools:end -->
|
|
104
168
|
|
|
105
169
|
## Resources & prompts
|
|
106
170
|
|
|
107
171
|
The server also exposes read-only **resources** for self-discovery — `uptimizr://capabilities`
|
|
108
|
-
(a machine-readable descriptor of event types, the tool catalog,
|
|
172
|
+
(a machine-readable descriptor of event types, the tool catalog, parameter semantics, and
|
|
173
|
+
`metrics`: the collector's whole semantic metric registry, with each metric's result grain, column
|
|
174
|
+
units, row JSON Schema, row limits, interpretation and caveats — ADR 0051) and
|
|
109
175
|
`uptimizr://scenes` (live scene ids) — and curated **prompts** (`weekly_scene_health`,
|
|
110
176
|
`attention_hotspots`, `xr_comfort_review`) that drive the tools above. A remote Streamable HTTP
|
|
111
177
|
transport is a deferred, auth-gated follow-up (ADR 0050 §7). See the
|
package/dist/capabilities.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { type EventType } from "@uptimizr/schema";
|
|
2
|
+
import { type ColumnSemantics, type DimensionId, type FilterId, type MetricCategory, type MetricComparison, type MetricGrain } from "@uptimizr/metrics";
|
|
2
3
|
/**
|
|
3
4
|
* One tool the server exposes, described for self-discovery: its name, a human
|
|
4
|
-
* title, what it returns, and the parameter names it accepts.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* title, what it returns, and the parameter names it accepts.
|
|
6
|
+
*
|
|
7
|
+
* Derived from the **semantic metric registry** (`@uptimizr/metrics`, ADR
|
|
8
|
+
* 0051 §1) rather than restated here, so the catalog cannot drift from the
|
|
9
|
+
* metrics the collector can actually compute. `params` are the request
|
|
10
|
+
* parameters of the underlying query endpoint — the definitive *input schema*
|
|
11
|
+
* of a registered MCP tool is the one returned by `tools/list`.
|
|
7
12
|
*/
|
|
8
13
|
export interface CapabilityToolDescriptor {
|
|
9
14
|
name: string;
|
|
@@ -16,11 +21,58 @@ export interface CapabilityParamDescriptor {
|
|
|
16
21
|
name: string;
|
|
17
22
|
description: string;
|
|
18
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* One registry metric, serialised for an agent: everything in the registry
|
|
26
|
+
* entry except the SQL `builder` (an implementation detail with no meaning
|
|
27
|
+
* outside `@uptimizr/db`), with the Zod `row` schema replaced by its JSON
|
|
28
|
+
* Schema so a client with no Zod can still validate or shape a result.
|
|
29
|
+
*/
|
|
30
|
+
export interface CapabilityMetricDescriptor {
|
|
31
|
+
id: string;
|
|
32
|
+
title: string;
|
|
33
|
+
description: string;
|
|
34
|
+
category: MetricCategory;
|
|
35
|
+
/** What one row represents. */
|
|
36
|
+
grain: MetricGrain;
|
|
37
|
+
/** The collector route it is served on, when it has one. */
|
|
38
|
+
endpoint?: {
|
|
39
|
+
method: "GET";
|
|
40
|
+
path: string;
|
|
41
|
+
pathParams?: readonly FilterId[];
|
|
42
|
+
};
|
|
43
|
+
/** Group-by dimensions the rows are keyed by. */
|
|
44
|
+
dimensions: readonly DimensionId[];
|
|
45
|
+
/** Accepted request parameters. */
|
|
46
|
+
filters: readonly FilterId[];
|
|
47
|
+
/** JSON Schema of one result row. */
|
|
48
|
+
row: Record<string, unknown>;
|
|
49
|
+
/** Per-column semantics: description, unit, which column is the measure/label. */
|
|
50
|
+
columns: Readonly<Record<string, ColumnSemantics>>;
|
|
51
|
+
/** Registry-declared caps, so no consumer asks for an unbounded payload. */
|
|
52
|
+
limits: {
|
|
53
|
+
maxRows: number;
|
|
54
|
+
maxSummaryRows: number;
|
|
55
|
+
};
|
|
56
|
+
/** How to read the result. */
|
|
57
|
+
interpretation: string;
|
|
58
|
+
/** Small-sample, capture-gating and sampling-rate warnings. */
|
|
59
|
+
caveats: readonly string[];
|
|
60
|
+
/** Capture channels (ADR 0012) that must be enabled for it to have data. */
|
|
61
|
+
sourceChannels: readonly EventType[];
|
|
62
|
+
related: readonly string[];
|
|
63
|
+
comparable?: MetricComparison;
|
|
64
|
+
/**
|
|
65
|
+
* `true` for a **resource** read (a single stored object such as a session
|
|
66
|
+
* descriptor) rather than an aggregation over the event stream.
|
|
67
|
+
*/
|
|
68
|
+
resource: boolean;
|
|
69
|
+
}
|
|
19
70
|
/**
|
|
20
71
|
* Machine-readable capabilities/schema descriptor an agent can read (via the
|
|
21
72
|
* `uptimizr://capabilities` resource) to learn what it can ask before guessing.
|
|
22
73
|
* It is strictly a description of the **read-only** surface — event types, the
|
|
23
|
-
* tool catalog, and parameter semantics — and never itself
|
|
74
|
+
* metric registry, the tool catalog, and parameter semantics — and never itself
|
|
75
|
+
* queries any data.
|
|
24
76
|
*/
|
|
25
77
|
export interface CapabilitiesDescriptor {
|
|
26
78
|
/** Wire-format version of the event schema (`@uptimizr/schema`). */
|
|
@@ -33,11 +85,16 @@ export interface CapabilitiesDescriptor {
|
|
|
33
85
|
params: readonly CapabilityParamDescriptor[];
|
|
34
86
|
/** The read-only tool catalog (each entry is one aggregate query endpoint). */
|
|
35
87
|
tools: readonly CapabilityToolDescriptor[];
|
|
88
|
+
/**
|
|
89
|
+
* The full semantic metric registry: units, grain, dimensions, row schema,
|
|
90
|
+
* limits, interpretation and caveats per metric (ADR 0051 §1).
|
|
91
|
+
*/
|
|
92
|
+
metrics: readonly CapabilityMetricDescriptor[];
|
|
36
93
|
/** Human-oriented notes about scope and discovery. */
|
|
37
94
|
notes: readonly string[];
|
|
38
95
|
}
|
|
39
96
|
/**
|
|
40
|
-
* Build the capabilities descriptor from the
|
|
97
|
+
* Build the capabilities descriptor from the metric registry and the event
|
|
41
98
|
* schema. Pure and synchronous — it introspects definitions only, never the
|
|
42
99
|
* collector, so it is safe to serve as a static resource.
|
|
43
100
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAErB,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED,+DAA+D;AAC/D,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,cAAc,CAAC;IACzB,+BAA+B;IAC/B,KAAK,EAAE,WAAW,CAAC;IACnB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAA;KAAE,CAAC;IAC7E,iDAAiD;IACjD,UAAU,EAAE,SAAS,WAAW,EAAE,CAAC;IACnC,mCAAmC;IACnC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC7B,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,kFAAkF;IAClF,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;IACnD,4EAA4E;IAC5E,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,8BAA8B;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,4EAA4E;IAC5E,cAAc,EAAE,SAAS,SAAS,EAAE,CAAC;IACrC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,EAAE,IAAI,CAAC;IACf,oEAAoE;IACpE,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IACjC,0DAA0D;IAC1D,MAAM,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAC7C,+EAA+E;IAC/E,KAAK,EAAE,SAAS,wBAAwB,EAAE,CAAC;IAC3C;;;OAGG;IACH,OAAO,EAAE,SAAS,0BAA0B,EAAE,CAAC;IAC/C,sDAAsD;IACtD,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAmCD;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,sBAAsB,CA8C1D"}
|
package/dist/capabilities.js
CHANGED
|
@@ -1,58 +1,84 @@
|
|
|
1
1
|
import { EVENT_TYPES, SCHEMA_VERSION } from "@uptimizr/schema";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { FILTER_TARGETS, allMetrics, isResourceMetric, } from "@uptimizr/metrics";
|
|
4
|
+
/** Every request parameter a metric accepts: its path params, then its filters. */
|
|
5
|
+
function paramsOf(metric) {
|
|
6
|
+
return [...(metric.endpoint?.pathParams ?? []), ...metric.filters];
|
|
7
|
+
}
|
|
8
|
+
/** Serialise one registry entry, dropping `builder` and unwrapping `row`. */
|
|
9
|
+
function toMetricDescriptor(metric) {
|
|
10
|
+
const row = z.toJSONSchema(metric.row, {
|
|
11
|
+
io: "output",
|
|
12
|
+
unrepresentable: "any",
|
|
13
|
+
});
|
|
14
|
+
delete row.$schema;
|
|
15
|
+
return {
|
|
16
|
+
id: metric.id,
|
|
17
|
+
title: metric.title,
|
|
18
|
+
description: metric.description,
|
|
19
|
+
category: metric.category,
|
|
20
|
+
grain: metric.grain,
|
|
21
|
+
...(metric.endpoint ? { endpoint: metric.endpoint } : {}),
|
|
22
|
+
dimensions: metric.dimensions,
|
|
23
|
+
filters: metric.filters,
|
|
24
|
+
row,
|
|
25
|
+
columns: metric.columns,
|
|
26
|
+
limits: metric.limits,
|
|
27
|
+
interpretation: metric.interpretation,
|
|
28
|
+
caveats: metric.caveats,
|
|
29
|
+
sourceChannels: metric.sourceChannels,
|
|
30
|
+
related: metric.related,
|
|
31
|
+
...(metric.comparable ? { comparable: metric.comparable } : {}),
|
|
32
|
+
resource: isResourceMetric(metric),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
25
35
|
/**
|
|
26
|
-
* Build the capabilities descriptor from the
|
|
36
|
+
* Build the capabilities descriptor from the metric registry and the event
|
|
27
37
|
* schema. Pure and synchronous — it introspects definitions only, never the
|
|
28
38
|
* collector, so it is safe to serve as a static resource.
|
|
29
39
|
*/
|
|
30
40
|
export function buildCapabilities() {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
const metrics = allMetrics();
|
|
42
|
+
const served = metrics.filter((metric) => metric.endpoint != null);
|
|
43
|
+
const tools = served.map((metric) => ({
|
|
44
|
+
name: metric.id,
|
|
45
|
+
title: metric.title,
|
|
46
|
+
description: metric.description,
|
|
47
|
+
params: paramsOf(metric),
|
|
36
48
|
}));
|
|
37
49
|
const usedParams = new Set();
|
|
38
|
-
for (const
|
|
39
|
-
for (const
|
|
40
|
-
usedParams.add(
|
|
50
|
+
for (const metric of served)
|
|
51
|
+
for (const param of paramsOf(metric))
|
|
52
|
+
usedParams.add(param);
|
|
41
53
|
const params = [...usedParams]
|
|
42
54
|
.sort()
|
|
43
|
-
.map((name) => ({ name, description:
|
|
55
|
+
.map((name) => ({ name, description: FILTER_TARGETS[name].description }));
|
|
44
56
|
return {
|
|
45
57
|
schemaVersion: SCHEMA_VERSION,
|
|
46
58
|
readOnly: true,
|
|
47
59
|
eventTypes: EVENT_TYPES,
|
|
48
60
|
params,
|
|
49
61
|
tools,
|
|
62
|
+
metrics: metrics.map(toMetricDescriptor),
|
|
50
63
|
notes: [
|
|
51
64
|
"This MCP surface is strictly read-only: aggregate, privacy-preserving queries only. " +
|
|
52
65
|
"There are no ingestion, mutation, or raw per-session event tools (ADR 0003 / ADR 0017).",
|
|
66
|
+
"`metrics` is the collector's semantic metric registry (ADR 0051 §1): for each metric it " +
|
|
67
|
+
"gives the result `grain` (what one row is), the `columns` with their units, the JSON " +
|
|
68
|
+
"Schema of a row, `limits`, how to read it (`interpretation`) and how far to trust it " +
|
|
69
|
+
"(`caveats`). Read a metric's caveats before quoting its numbers.",
|
|
70
|
+
"`sourceChannels` names the capture channels (ADR 0012) that feed a metric. If a project " +
|
|
71
|
+
"has that channel disabled or sampled down, the metric is empty or proportional rather " +
|
|
72
|
+
"than exact — say so instead of reporting a zero as a finding.",
|
|
73
|
+
"`tools` lists the registry's served read surface and the request parameters of each " +
|
|
74
|
+
"underlying endpoint. It is exactly the set this server registers, because the tool " +
|
|
75
|
+
"catalog is generated from the same registry (ADR 0051 §1) — the authoritative input " +
|
|
76
|
+
"and output schemas of a registered tool are still the ones returned by `tools/list`.",
|
|
53
77
|
"Enumerate the concrete scene ids for the `scene` parameter with the uptimizr://scenes " +
|
|
54
78
|
"resource or the list_scenes tool; enumerate sessions with the list_sessions tool.",
|
|
55
79
|
"All time ranges use epoch-millisecond `since`/`until`. Omit both for all-time.",
|
|
80
|
+
"The same registry drives the collector's OpenAPI document at GET /api/v1/openapi.json, " +
|
|
81
|
+
"which describes every endpoint below with its parameters and response schema.",
|
|
56
82
|
],
|
|
57
83
|
};
|
|
58
84
|
}
|
package/dist/capabilities.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAkB,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ import { type CollectorClient } from "@uptimizr/agent-core";
|
|
|
7
7
|
* collector's JSON (ADR 0005 / ADR 0017). Alongside the tools it exposes
|
|
8
8
|
* capability-discovery **resources** and curated analysis **prompts** so agents
|
|
9
9
|
* can self-orient (ADR 0050 §7).
|
|
10
|
+
*
|
|
11
|
+
* The tool catalog is generated from the `@uptimizr/db` metric registry
|
|
12
|
+
* (ADR 0051 §1), so `tools/list` covers every metric the collector serves on an
|
|
13
|
+
* endpoint. Each tool advertises the registry-derived `outputSchema` and returns
|
|
14
|
+
* both `structuredContent` (the typed `{ rows }` envelope) and the `content`
|
|
15
|
+
* text a client without structured-output support still reads.
|
|
10
16
|
*/
|
|
11
17
|
export declare function createMcpServer(client: CollectorClient): McpServer;
|
|
12
18
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAsCvE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAqClE"}
|
package/dist/server.js
CHANGED
|
@@ -1,8 +1,42 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
2
3
|
import { readTools } from "@uptimizr/agent-core";
|
|
3
4
|
import { registerResources } from "./resources.js";
|
|
4
5
|
import { registerPrompts } from "./prompts.js";
|
|
5
6
|
import { version } from "./version.js";
|
|
7
|
+
/**
|
|
8
|
+
* Normalise a collector response into the `{ rows }` envelope every tool's
|
|
9
|
+
* `outputSchema` declares. Aggregate endpoints already return an array; the
|
|
10
|
+
* single-object reads (a session descriptor, a scene representation, a one-row
|
|
11
|
+
* summary) become a one-element array so a client can treat every tool's
|
|
12
|
+
* structured result the same way. A `204`-style empty body becomes no rows.
|
|
13
|
+
*/
|
|
14
|
+
function toRows(data) {
|
|
15
|
+
if (Array.isArray(data))
|
|
16
|
+
return data;
|
|
17
|
+
if (data == null)
|
|
18
|
+
return [];
|
|
19
|
+
return [data];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validate the rows against the tool's registry-derived output schema and
|
|
23
|
+
* return the **parsed** result as the structured payload.
|
|
24
|
+
*
|
|
25
|
+
* The registry's numeric columns are strict `z.number()`: since ADR 0051 §2 the
|
|
26
|
+
* *collector* guarantees numbers, coercing each dialect's wire format
|
|
27
|
+
* (ClickHouse's string-encoded 64-bit integers, `pg`'s `int8`) at the single
|
|
28
|
+
* point rows leave its driver. So this is a check, not a repair — the advertised
|
|
29
|
+
* schema describes the API, and normalising here would hide a store regression.
|
|
30
|
+
*
|
|
31
|
+
* If the rows do not match the schema the raw rows are passed through; the SDK's
|
|
32
|
+
* own output validation then reports the offending column by name, which is the
|
|
33
|
+
* honest outcome for a collector that is out of contract.
|
|
34
|
+
*/
|
|
35
|
+
function structuredRows(outputSchema, data) {
|
|
36
|
+
const rows = toRows(data);
|
|
37
|
+
const parsed = z.object(outputSchema).safeParse({ rows });
|
|
38
|
+
return parsed.success ? parsed.data : { rows };
|
|
39
|
+
}
|
|
6
40
|
/**
|
|
7
41
|
* Build the Uptimizr MCP server: a read-only `McpServer` whose tools each wrap
|
|
8
42
|
* one collector query endpoint via the injected `CollectorClient`. The server
|
|
@@ -10,6 +44,12 @@ import { version } from "./version.js";
|
|
|
10
44
|
* collector's JSON (ADR 0005 / ADR 0017). Alongside the tools it exposes
|
|
11
45
|
* capability-discovery **resources** and curated analysis **prompts** so agents
|
|
12
46
|
* can self-orient (ADR 0050 §7).
|
|
47
|
+
*
|
|
48
|
+
* The tool catalog is generated from the `@uptimizr/db` metric registry
|
|
49
|
+
* (ADR 0051 §1), so `tools/list` covers every metric the collector serves on an
|
|
50
|
+
* endpoint. Each tool advertises the registry-derived `outputSchema` and returns
|
|
51
|
+
* both `structuredContent` (the typed `{ rows }` envelope) and the `content`
|
|
52
|
+
* text a client without structured-output support still reads.
|
|
13
53
|
*/
|
|
14
54
|
export function createMcpServer(client) {
|
|
15
55
|
const server = new McpServer({ name: "uptimizr-mcp", version }, { capabilities: { tools: {}, resources: {}, prompts: {} } });
|
|
@@ -18,11 +58,18 @@ export function createMcpServer(client) {
|
|
|
18
58
|
title: tool.title,
|
|
19
59
|
description: tool.description,
|
|
20
60
|
inputSchema: tool.inputSchema,
|
|
61
|
+
...(tool.outputSchema ? { outputSchema: tool.outputSchema } : {}),
|
|
21
62
|
}, async (args) => {
|
|
22
63
|
try {
|
|
23
64
|
const { path, params } = tool.buildRequest(args);
|
|
24
65
|
const data = await client.get(path, params);
|
|
25
|
-
|
|
66
|
+
const text = JSON.stringify(data);
|
|
67
|
+
if (!tool.outputSchema)
|
|
68
|
+
return { content: [{ type: "text", text }] };
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: "text", text }],
|
|
71
|
+
structuredContent: structuredRows(tool.outputSchema, data),
|
|
72
|
+
};
|
|
26
73
|
}
|
|
27
74
|
catch (err) {
|
|
28
75
|
const message = err instanceof Error ? err.message : String(err);
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAwB,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/llms.txt
CHANGED
|
@@ -10,9 +10,33 @@
|
|
|
10
10
|
- [Integration & API reference](https://github.com/RaananW/Uptimizr/blob/main/docs/integration.md): the underlying query endpoints.
|
|
11
11
|
- [Architecture Decision Records](https://github.com/RaananW/Uptimizr/tree/main/docs/adr): privacy model (0003), thin backends (0005), consumer-facing agents (0017).
|
|
12
12
|
|
|
13
|
+
## Tools (read-only)
|
|
14
|
+
|
|
15
|
+
<!-- generated:registry-tool-names:start — generated by `pnpm gen:docs`; edit the metric registry, not this list -->
|
|
16
|
+
|
|
17
|
+
`list_sessions`, `session_meta`, `scene_representation`, `list_scenes`, `timeseries`,
|
|
18
|
+
`event_counts`, `pointer_heatmap`, `mesh_uv_heatmap`, `world_heatmap`, `world_heatmap_stats`,
|
|
19
|
+
`gaze_heatmap`, `gaze_heatmap_stats`, `camera_heatmap`, `view_coverage_histogram`,
|
|
20
|
+
`position_heatmap`, `session_trajectory`, `aggregate_paths`, `scene_coverage`, `camera_distance`,
|
|
21
|
+
`click_rays`, `flow_links`, `top_meshes`, `mesh_sources`, `mesh_trend`, `mesh_dwell`,
|
|
22
|
+
`mesh_blind_spots`, `mesh_interaction_kinds`, `mesh_reachability`, `dead_clicks`, `rage_clicks`,
|
|
23
|
+
`hover_dwell`, `interaction_sources`, `top_input_actions`, `camera_gestures`, `navigation_stats`,
|
|
24
|
+
`backtrack_ratio`, `perf_summary`, `render_scale_truth`, `perf_distribution`, `fps_histogram`,
|
|
25
|
+
`frame_time_percentiles`, `jank_rate`, `perf_churn`, `perf_by_device`, `perf_by_scene`,
|
|
26
|
+
`perf_heatmap`, `compile_stalls`, `resource_summary`, `resource_percentiles`, `stability_counts`,
|
|
27
|
+
`graphics_diagnostics`, `error_heatmap`, `rendering_technology`, `capability_changes`,
|
|
28
|
+
`xr_rotation`, `xr_sources`, `xr_abandonment`, `xr_locomotion`, `xr_tracking_quality`,
|
|
29
|
+
`boundary_heatmap`, `boundary_heatmap_stats`, `xr_boundary_contacts`,
|
|
30
|
+
`ar_placement_time_to_place`, `ar_placement_attempts`, `ar_placement_surfaces`, `funnel`,
|
|
31
|
+
`scene_retention`, `load_bounce_funnel`, `variant_leaderboard`
|
|
32
|
+
|
|
33
|
+
<!-- generated:registry-tool-names:end -->
|
|
34
|
+
|
|
13
35
|
## Key exports
|
|
14
36
|
|
|
15
37
|
- `createMcpServer(client)` — build the read-only MCP server.
|
|
16
38
|
- `createCollectorClient(config)` — the thin GET-only collector client.
|
|
17
39
|
- `readMcpConfig()` — read `UPTIMIZR_COLLECTOR_URL` + `UPTIMIZR_API_KEY` from the environment.
|
|
18
|
-
- `readTools` — the read-only tool catalog (one entry per query endpoint)
|
|
40
|
+
- `readTools` — the read-only tool catalog (one entry per query endpoint), generated from the
|
|
41
|
+
`@uptimizr/metrics` metric registry: 69 tools, each with an input schema, an MCP `outputSchema` and the
|
|
42
|
+
metric's interpretation notes and caveats in its description (ADR 0051).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uptimizr/mcp",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Read-only Model Context Protocol (MCP) server over an Uptimizr collector's query API — let an agent ask questions of your own 3D analytics, on your own infrastructure.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"uptimizr",
|
|
@@ -49,8 +49,9 @@
|
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
51
51
|
"zod": "^4.5.4",
|
|
52
|
-
"@uptimizr/agent-core": "1.0
|
|
53
|
-
"@uptimizr/
|
|
52
|
+
"@uptimizr/agent-core": "1.1.0",
|
|
53
|
+
"@uptimizr/metrics": "0.1.0",
|
|
54
|
+
"@uptimizr/schema": "1.1.0"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
57
|
"@types/node": "^26.4.1",
|