@extn/segi-mcp 0.1.0 → 0.2.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.
Files changed (3) hide show
  1. package/README.md +32 -2
  2. package/dist/index.js +35 -0
  3. package/package.json +12 -10
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @extn/segi-mcp
2
2
 
3
- Read-only MCP server for the **segi** error-monitoring platform. Connect
3
+ MCP server for the **segi** error-monitoring platform. Connect
4
4
  Claude (Code / Desktop) or any MCP client to your segi organization and let
5
5
  the agent read issues, events, and stack traces — then diagnose and fix the
6
6
  bugs in your own codebase.
@@ -35,7 +35,7 @@ Environment variables:
35
35
  | `get_event` | Full detail of a single event by eventId |
36
36
  | `get_project_stats` | Project dashboard summary + 24h timeseries |
37
37
 
38
- All tools are read-only. Keys are org-scoped (optionally restricted to a
38
+ Monitoring tools are read-only. Analytics configuration writes require a new key with explicit analytics-write permission. Existing keys remain read-only. Keys are org-scoped (optionally restricted to a
39
39
  single project) and rate-limited per minute; revoke them any time from the
40
40
  console — revocation is immediate.
41
41
 
@@ -44,3 +44,33 @@ console — revocation is immediate.
44
44
  - "segi에서 지금 제일 시끄러운 에러가 뭐야? 원인 찾아서 고쳐줘."
45
45
  - "What errors spiked after yesterday's deploy? Show me the stack traces."
46
46
  - "Fix the top unresolved FATAL issue in the api project."
47
+
48
+ ## Analytics workflow
49
+
50
+ New tools require the server migration and the updated MCP package to be deployed together.
51
+
52
+ | Tool | Purpose |
53
+ |---|---|
54
+ | `get_analytics_instrumentation_guide` | Supported browser instrumentation and verification contract |
55
+ | `list_analytics_items` | Search received pages/events and registered definitions; 20 results per page |
56
+ | `list_analytics_definitions` | Get definitions and saved funnels, including id/version |
57
+ | `get_analytics_receipts` | Latest five receipt timestamps and page paths for one step |
58
+ | `analyze_funnel` | Ordered, same-session counts and independent observed counts per step |
59
+ | `save_analytics_definition` | Create/update an event definition or saved funnel; requires explicit write permission |
60
+
61
+ Ask your agent to inspect existing events and code before adding instrumentation. Emit
62
+ `Segi.replay.event("purchase_done", { itemCount: 2 })` in the browser only after confirmed success.
63
+ Recording must be enabled and replay initialized. Do not use this browser API in server handlers.
64
+ Server-event/session correlation and exactly-once deduplication are not supplied by this workflow.
65
+ Never send raw forms, credentials, card data, or personal identifiers as properties.
66
+
67
+ Register `kind: "event"`, `eventName`, `name` (display name), `description` and optional
68
+ `properties: [{name: "itemCount", type: "number", description: "Purchased item count"}]`.
69
+ For a saved funnel use `kind: "funnel"`, `name`, and `steps` (2–6 comma-separated conditions).
70
+ Update with the existing `id` and `version`; conflicts require re-reading before retrying.
71
+ Saving definitions does not emit events. Trigger a test action and compare receipt timestamps
72
+ against the test time, then validate the funnel. Do not claim verified delivery from code changes alone.
73
+
74
+ Definitions are project-scoped. OWNER/ADMIN may create a key with analytics writes enabled;
75
+ other keys can inspect but cannot save. Changes record the key ID and revision. This permission
76
+ does not grant issue triage, billing, or project-administration writes.
package/dist/index.js CHANGED
@@ -62,12 +62,37 @@ var PAGING_PROPS = {
62
62
  description: "Items per page (max 100). Default 20."
63
63
  }
64
64
  };
65
+ var ANALYTICS_GUIDE = `Use list_projects, then list_analytics_items and list_analytics_definitions before adding instrumentation.
66
+ Automatic page_view events require browser replay initialization and recording enabled in the project. Next.js SegiProvider tracks pathname changes; other SPAs must call Segi.replay.notifyRouteChange() after navigation.
67
+ For a browser business action, call Segi.replay.event("purchase_done", { itemCount: 2 }) only after confirmed success, never merely on a button click. Do not send personal data, access tokens, passwords, card details, or raw form payloads.
68
+ Use the installed SDK and its public API. Segi.replay.event is a browser-session API; do not call it in a server handler or invent a server ingestion endpoint. Server business-event/session correlation is not supported by this workflow yet. For a server-confirmed operation, report success to the initiating browser and emit there; document events missed when that browser is gone.
69
+ Check existing instrumentation, avoid duplicate initialization and duplicate event calls. There is no exactly-once guarantee or deduplication key in the current replay API.
70
+ Define a stable event name, a human display name, exact success condition, and up to 20 non-sensitive property definitions (name/type/description). Use save_analytics_definition only with an explicitly analytics-write-enabled key. Definition registration does not prove receipt.
71
+ Run the consuming service's tests, trigger a real test action, then inspect get_analytics_receipts and list_analytics_items. Report code changes and observed receipt separately; do not claim data was received unless verified. get_analytics_receipts reports the latest five timestamps and page paths in the requested range; compare timestamps to your test.
72
+ Use analyze_funnel to validate same-session ordered progression. Funnel steps use page_view:/path or custom:name, comma separated, up to 6. Path matching excludes query/hash and is exact/case-sensitive; full http(s) URL conditions match the complete stored URL. Same-timestamp events have no inferred order. All stages must occur within the chosen period.
73
+ Saved funnels require at least two steps. Read the existing id/version before updating, and re-read on a conflict. Read-only keys can inspect items/receipts/definitions/funnels but cannot write configuration.`;
74
+ var analyticsProject = { projectId: { type: "string", pattern: "^[0-9]+$", description: "Project ID from list_projects." } };
75
+ var analyticsPeriod = { period: { type: "string", enum: ["24h", "7d", "30d"], description: "Default 7d." } };
76
+ var analyticsTools = [
77
+ { name: "get_analytics_instrumentation_guide", description: "Get the supported browser analytics instrumentation and verification workflow, including server limitations.", inputSchema: { type: "object", properties: {} }, annotations: { readOnlyHint: true } },
78
+ { name: "list_analytics_items", description: "Discover collected pages/custom events and registered event descriptions. Counts and receipt timestamps are scoped to the project and period.", inputSchema: { type: "object", properties: { ...analyticsProject, ...analyticsPeriod, kind: { type: "string", enum: ["page_view", "custom"] }, search: { type: "string" }, page: { type: "number" } }, required: ["projectId"] }, annotations: { readOnlyHint: true } },
79
+ { name: "list_analytics_definitions", description: "Read event definitions and saved funnels, including id/version for safe updates. Registered is not the same as received.", inputSchema: { type: "object", properties: analyticsProject, required: ["projectId"] }, annotations: { readOnlyHint: true } },
80
+ { name: "get_analytics_receipts", description: "Verify recent receipt timestamps and page paths for one step. No raw metadata or personal identifiers are returned.", inputSchema: { type: "object", properties: { ...analyticsProject, ...analyticsPeriod, step: { type: "string" } }, required: ["projectId", "step"] }, annotations: { readOnlyHint: true } },
81
+ { name: "analyze_funnel", description: "Validate ordered, same-session funnel counts using collected events.", inputSchema: { type: "object", properties: { ...analyticsProject, ...analyticsPeriod, steps: { type: "string" } }, required: ["projectId", "steps"] }, annotations: { readOnlyHint: true } },
82
+ { name: "save_analytics_definition", description: "Create/update an event definition or saved funnel. Requires analytics-write permission explicitly enabled on the API key. Pass id and current version for updates; this does not emit events.", inputSchema: { type: "object", properties: { ...analyticsProject, kind: { type: "string", enum: ["event", "funnel"] }, name: { type: "string" }, eventName: { type: "string" }, description: { type: "string" }, steps: { type: "string" }, id: { type: "string" }, version: { type: "integer" }, properties: { type: "array", items: { type: "object", properties: { name: { type: "string" }, type: { type: "string", enum: ["string", "number", "boolean"] }, description: { type: "string" } }, required: ["name", "type", "description"] } } }, required: ["projectId", "kind", "name"] }, annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false } }
83
+ ];
84
+ async function analyticsWrite(projectId, body) {
85
+ const res = await fetch(`${API_BASE}/api/mcp/v1/projects/${encodeURIComponent(projectId)}/analytics/definitions`, { method: "POST", headers: { authorization: `Bearer ${SECRET_KEY}`, "content-type": "application/json" }, body: JSON.stringify(body) });
86
+ if (!res.ok) throw new Error(`Analytics write failed (${res.status}): ${(await res.text()).slice(0, 500)}`);
87
+ return res.json();
88
+ }
65
89
  var server = new Server(
66
90
  { name: "segi-mcp", version: "0.1.0" },
67
91
  { capabilities: { tools: {} } }
68
92
  );
69
93
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
70
94
  tools: [
95
+ ...analyticsTools,
71
96
  {
72
97
  name: "list_projects",
73
98
  description: "List the segi projects this API key can read (id, name, slug, platform). Call this first to discover project ids \u2014 every per-project tool needs one.",
@@ -193,6 +218,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
193
218
  const args = rawArgs;
194
219
  const projectId = args.projectId;
195
220
  try {
221
+ if (name === "get_analytics_instrumentation_guide") return textResult(ANALYTICS_GUIDE);
222
+ if (analyticsTools.some((tool) => tool.name === name)) {
223
+ if (!projectId || !/^\d+$/.test(projectId)) throw new Error("A valid projectId is required.");
224
+ if (name === "save_analytics_definition") {
225
+ const { projectId: _, ...body } = rawArgs;
226
+ return textResult(await analyticsWrite(projectId, body));
227
+ }
228
+ const action = { list_analytics_items: "catalog", list_analytics_definitions: "definitions", get_analytics_receipts: "detail", analyze_funnel: "funnel" };
229
+ return textResult(await apiGet(`/api/mcp/v1/projects/${encodeURIComponent(projectId)}/analytics/${action[name]}`, { period: args.period, kind: args.kind, search: args.search, page: args.page, step: args.step, steps: args.steps }));
230
+ }
196
231
  switch (name) {
197
232
  case "list_projects":
198
233
  return textResult(await apiGet("/api/mcp/v1/projects"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@extn/segi-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "MCP server that lets an AI agent (Claude) read segi error-monitoring data — issues, events, stack traces, project stats — using an organization API key",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -8,17 +8,13 @@
8
8
  "bin": {
9
9
  "segi-mcp": "./dist/index.js"
10
10
  },
11
- "files": ["dist", "README.md"],
11
+ "files": [
12
+ "dist",
13
+ "README.md"
14
+ ],
12
15
  "publishConfig": {
13
16
  "access": "public"
14
17
  },
15
- "scripts": {
16
- "build": "tsup",
17
- "dev": "tsup --watch",
18
- "typecheck": "tsc -p tsconfig.json --noEmit",
19
- "clean": "rm -rf dist",
20
- "prepublishOnly": "pnpm run clean && pnpm run build"
21
- },
22
18
  "dependencies": {
23
19
  "@modelcontextprotocol/sdk": "^1.0.0"
24
20
  },
@@ -26,5 +22,11 @@
26
22
  "@types/node": "^22.7.0",
27
23
  "tsup": "^8.3.0",
28
24
  "typescript": "^5.6.3"
25
+ },
26
+ "scripts": {
27
+ "build": "tsup",
28
+ "dev": "tsup --watch",
29
+ "typecheck": "tsc -p tsconfig.json --noEmit",
30
+ "clean": "rm -rf dist"
29
31
  }
30
- }
32
+ }