@pingroom/sdk 0.2.0 → 0.4.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.
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Live-status streams — the wire contract for driving a Live Activity.
3
+ *
4
+ * A stream is keyed by `correlation_id`: the first ping starts a live card on
5
+ * every room member's lock screen (one alert), further `running` pings move it
6
+ * silently, and the first `done`/`failed` sends one completion alert and ends
7
+ * it. See https://pingroom.io/liveactivities.md.
8
+ *
9
+ * Three producers speak this contract. This SDK reaches the two machine ones:
10
+ * - a room's **incoming webhook** (Pro) — `sendIncomingWebhook()`
11
+ * - an **agent credential** — `pr.live.*` (needs `pingroom:live:write`)
12
+ *
13
+ * The third is a signed-in person driving a stream from the app composer over
14
+ * `POST /api/rooms/{inviteCode}/live` with their own Human JWT. It sends this
15
+ * same body minus `live_status.agent_id` (stripped server-side), so these
16
+ * builders describe it too — but it is not an agent route and has no client
17
+ * here.
18
+ *
19
+ * Not to be confused with `liveActivity.*` in ./liveActivity.ts, which builds
20
+ * the frozen *native* `{ attributes, content_state }` push shape for tests and
21
+ * tooling. These builders produce the `live_status` object you actually send.
22
+ */
23
+ import type { LiveActivityTemplate } from './liveActivity.js';
24
+ export type LiveStatusState = 'running' | 'done' | 'failed';
25
+ /** Legacy rendering category. Prefer `template`; `alert` selects urgent styling. */
26
+ export type LiveStatusCategory = 'status' | 'steps' | 'alert';
27
+ export interface LiveStatusMetric {
28
+ label: string;
29
+ value: string;
30
+ }
31
+ export interface LiveStatusOption {
32
+ value: string;
33
+ label: string;
34
+ }
35
+ export interface LiveStatusSide {
36
+ label: string;
37
+ value: string;
38
+ iconSvg?: string;
39
+ }
40
+ /**
41
+ * The `live_status` object. Only `state` is required; every other field is read
42
+ * by the template you selected.
43
+ *
44
+ * `template` and `steps` are fixed at stream creation — a later ping cannot
45
+ * re-template a running card. Content set at creation is sticky, so a sparse
46
+ * update carrying just `progress` keeps rendering the full template. The
47
+ * terminal leg is sticky too: `{ state: 'done' }` alone keeps the scoreboard,
48
+ * metrics grid, deadline and accent on the final frame.
49
+ */
50
+ export interface LiveStatus {
51
+ state: LiveStatusState;
52
+ template?: LiveActivityTemplate;
53
+ category?: LiveStatusCategory;
54
+ message?: string;
55
+ /** 0..1 — the progress bar / Dynamic Island gauge. */
56
+ progress?: number;
57
+ /** 2–8 labels. Required on the first ping of a `steps` stream; immutable after. */
58
+ steps?: string[];
59
+ /** Index into `steps`; the only mutable steps field. */
60
+ current_step?: number;
61
+ /** Up to 3 counters, for the `metrics` template. */
62
+ metrics?: LiveStatusMetric[];
63
+ /** Epoch seconds the `countdown` template counts down to. */
64
+ deadline_at?: number;
65
+ /** Epoch seconds; renders a live ETA on `status`/`progress`. */
66
+ eta_at?: number;
67
+ /** The ask, for the `question` template. */
68
+ prompt?: string;
69
+ /** Up to 4 choices, for the `question` template. */
70
+ options?: LiveStatusOption[];
71
+ left?: LiveStatusSide;
72
+ right?: LiveStatusSide;
73
+ center?: string;
74
+ /** Hex `#rrggbb` — a semantic accent for one frame (e.g. deadline red). */
75
+ accent_override?: string;
76
+ agent_id?: string;
77
+ }
78
+ /** The full body of a live-status ping. */
79
+ export interface LiveStatusPing {
80
+ correlation_id: string;
81
+ live_status: LiveStatus;
82
+ title?: string;
83
+ /** Quick-action slot 1–4 supplying the icon and sound. */
84
+ action?: number;
85
+ data?: Record<string, unknown>;
86
+ requires_ack?: boolean;
87
+ ack_timeout_seconds?: number;
88
+ }
89
+ export interface LiveStatusResult {
90
+ notification_id: string;
91
+ correlation_id: string;
92
+ /** `started` on creation, then `running` / `done` / `failed`. */
93
+ state: string;
94
+ idempotent: boolean;
95
+ action_state?: unknown;
96
+ }
97
+ /**
98
+ * The read-back shape from `GET .../live/{correlationId}`.
99
+ *
100
+ * EVERY stored `live_status` field is returned, not a step/progress subset — a
101
+ * `matchup` / `metrics` / `countdown` / `question` stream would otherwise be
102
+ * unresumable after a producer restart. Fields you never set come back as
103
+ * `null` rather than being omitted, so read them defensively.
104
+ *
105
+ * The server-side ownership stamps (`_webhook` / `_agent` / `_user`) are
106
+ * deliberately NOT returned — they are the authorization record, not client
107
+ * state.
108
+ */
109
+ export interface LiveStatusSnapshot {
110
+ notification_id: string;
111
+ correlation_id: string;
112
+ state: string | null;
113
+ progress: number | null;
114
+ message: string | null;
115
+ category: LiveStatusCategory | null;
116
+ template: LiveActivityTemplate | null;
117
+ agent_id: string | null;
118
+ accent_override: string | null;
119
+ eta_at: number | null;
120
+ deadline_at: number | null;
121
+ metrics: LiveStatusMetric[] | null;
122
+ prompt: string | null;
123
+ options: LiveStatusOption[] | null;
124
+ left: LiveStatusSide | null;
125
+ right: LiveStatusSide | null;
126
+ center: string | null;
127
+ steps: string[] | null;
128
+ current_step: number | null;
129
+ action_state?: unknown;
130
+ updated_at: string | null;
131
+ }
132
+ type Rest = Omit<LiveStatusPing, 'correlation_id' | 'live_status'>;
133
+ /**
134
+ * Builders for the common stream shapes. Each returns a body you can hand to
135
+ * `pr.live.push()` or `sendIncomingWebhook()`.
136
+ */
137
+ export declare const liveStatus: {
138
+ /** Default template: a title line plus a status dot, with optional progress. */
139
+ status(correlationId: string, live: Omit<LiveStatus, "template">, rest?: Rest): LiveStatusPing;
140
+ /** A segmented step tracker. `steps` is required on the first ping. */
141
+ steps(correlationId: string, live: Omit<LiveStatus, "template">, rest?: Rest): LiveStatusPing;
142
+ /** A determinate progress bar with an optional live ETA. */
143
+ progress(correlationId: string, live: Omit<LiveStatus, "template">, rest?: Rest): LiveStatusPing;
144
+ /** Up to 3 labelled counters. */
145
+ metrics(correlationId: string, live: Omit<LiveStatus, "template">, rest?: Rest): LiveStatusPing;
146
+ /** A large live timer counting down to `deadline_at`. */
147
+ countdown(correlationId: string, live: Omit<LiveStatus, "template">, rest?: Rest): LiveStatusPing;
148
+ /** A prompt with up to 4 options shown on the lock screen. */
149
+ question(correlationId: string, live: Omit<LiveStatus, "template">, rest?: Rest): LiveStatusPing;
150
+ /** Two sides plus a center score/clock. */
151
+ matchup(correlationId: string, live: Omit<LiveStatus, "template">, rest?: Rest): LiveStatusPing;
152
+ /**
153
+ * An urgent stream, delivered time-sensitive from the start so it breaks
154
+ * through Focus.
155
+ *
156
+ * This is a `category`, not a `template`: `alert` has no template equivalent,
157
+ * and it is the only way to start time-sensitive WITHOUT also setting
158
+ * `requires_ack` (which demands somebody tap). Fixed at creation, like
159
+ * `template`.
160
+ */
161
+ alert(correlationId: string, live: Omit<LiveStatus, "template" | "category">, rest?: Rest): LiveStatusPing;
162
+ /** Finish a stream. The one alert your stream earns. */
163
+ done(correlationId: string, message?: string, rest?: Rest): LiveStatusPing;
164
+ /** Finish a stream unsuccessfully. */
165
+ failed(correlationId: string, message?: string, rest?: Rest): LiveStatusPing;
166
+ };
167
+ export {};
168
+ //# sourceMappingURL=liveStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveStatus.d.ts","sourceRoot":"","sources":["../src/liveStatus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Live-status streams — the wire contract for driving a Live Activity.
3
+ *
4
+ * A stream is keyed by `correlation_id`: the first ping starts a live card on
5
+ * every room member's lock screen (one alert), further `running` pings move it
6
+ * silently, and the first `done`/`failed` sends one completion alert and ends
7
+ * it. See https://pingroom.io/liveactivities.md.
8
+ *
9
+ * Three producers speak this contract. This SDK reaches the two machine ones:
10
+ * - a room's **incoming webhook** (Pro) — `sendIncomingWebhook()`
11
+ * - an **agent credential** — `pr.live.*` (needs `pingroom:live:write`)
12
+ *
13
+ * The third is a signed-in person driving a stream from the app composer over
14
+ * `POST /api/rooms/{inviteCode}/live` with their own Human JWT. It sends this
15
+ * same body minus `live_status.agent_id` (stripped server-side), so these
16
+ * builders describe it too — but it is not an agent route and has no client
17
+ * here.
18
+ *
19
+ * Not to be confused with `liveActivity.*` in ./liveActivity.ts, which builds
20
+ * the frozen *native* `{ attributes, content_state }` push shape for tests and
21
+ * tooling. These builders produce the `live_status` object you actually send.
22
+ */
23
+ const ping = (correlationId, live, rest = {}) => ({
24
+ correlation_id: correlationId,
25
+ live_status: live,
26
+ ...rest,
27
+ });
28
+ /**
29
+ * Builders for the common stream shapes. Each returns a body you can hand to
30
+ * `pr.live.push()` or `sendIncomingWebhook()`.
31
+ */
32
+ export const liveStatus = {
33
+ /** Default template: a title line plus a status dot, with optional progress. */
34
+ status(correlationId, live, rest) {
35
+ return ping(correlationId, { template: 'status', ...live }, rest);
36
+ },
37
+ /** A segmented step tracker. `steps` is required on the first ping. */
38
+ steps(correlationId, live, rest) {
39
+ return ping(correlationId, { template: 'steps', ...live }, rest);
40
+ },
41
+ /** A determinate progress bar with an optional live ETA. */
42
+ progress(correlationId, live, rest) {
43
+ return ping(correlationId, { template: 'progress', ...live }, rest);
44
+ },
45
+ /** Up to 3 labelled counters. */
46
+ metrics(correlationId, live, rest) {
47
+ return ping(correlationId, { template: 'metrics', ...live }, rest);
48
+ },
49
+ /** A large live timer counting down to `deadline_at`. */
50
+ countdown(correlationId, live, rest) {
51
+ return ping(correlationId, { template: 'countdown', ...live }, rest);
52
+ },
53
+ /** A prompt with up to 4 options shown on the lock screen. */
54
+ question(correlationId, live, rest) {
55
+ return ping(correlationId, { template: 'question', ...live }, rest);
56
+ },
57
+ /** Two sides plus a center score/clock. */
58
+ matchup(correlationId, live, rest) {
59
+ return ping(correlationId, { template: 'matchup', ...live }, rest);
60
+ },
61
+ /**
62
+ * An urgent stream, delivered time-sensitive from the start so it breaks
63
+ * through Focus.
64
+ *
65
+ * This is a `category`, not a `template`: `alert` has no template equivalent,
66
+ * and it is the only way to start time-sensitive WITHOUT also setting
67
+ * `requires_ack` (which demands somebody tap). Fixed at creation, like
68
+ * `template`.
69
+ */
70
+ alert(correlationId, live, rest) {
71
+ return ping(correlationId, { category: 'alert', ...live }, rest);
72
+ },
73
+ /** Finish a stream. The one alert your stream earns. */
74
+ done(correlationId, message, rest) {
75
+ return ping(correlationId, { state: 'done', ...(message ? { message } : {}) }, rest);
76
+ },
77
+ /** Finish a stream unsuccessfully. */
78
+ failed(correlationId, message, rest) {
79
+ return ping(correlationId, { state: 'failed', ...(message ? { message } : {}) }, rest);
80
+ },
81
+ };
82
+ //# sourceMappingURL=liveStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveStatus.js","sourceRoot":"","sources":["../src/liveStatus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AA2HH,MAAM,IAAI,GAAG,CAAC,aAAqB,EAAE,IAAgB,EAAE,OAAa,EAAE,EAAkB,EAAE,CAAC,CAAC;IAC1F,cAAc,EAAE,aAAa;IAC7B,WAAW,EAAE,IAAI;IACjB,GAAG,IAAI;CACR,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,gFAAgF;IAChF,MAAM,CAAC,aAAqB,EAAE,IAAkC,EAAE,IAAW;QAC3E,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,aAAqB,EAAE,IAAkC,EAAE,IAAW;QAC1E,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC;IAED,4DAA4D;IAC5D,QAAQ,CAAC,aAAqB,EAAE,IAAkC,EAAE,IAAW;QAC7E,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACtE,CAAC;IAED,iCAAiC;IACjC,OAAO,CAAC,aAAqB,EAAE,IAAkC,EAAE,IAAW;QAC5E,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACrE,CAAC;IAED,yDAAyD;IACzD,SAAS,CAAC,aAAqB,EAAE,IAAkC,EAAE,IAAW;QAC9E,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACvE,CAAC;IAED,8DAA8D;IAC9D,QAAQ,CAAC,aAAqB,EAAE,IAAkC,EAAE,IAAW;QAC7E,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACtE,CAAC;IAED,2CAA2C;IAC3C,OAAO,CAAC,aAAqB,EAAE,IAAkC,EAAE,IAAW;QAC5E,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,aAAqB,EAAE,IAA+C,EAAE,IAAW;QACvF,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC;IAED,wDAAwD;IACxD,IAAI,CAAC,aAAqB,EAAE,OAAgB,EAAE,IAAW;QACvD,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACvF,CAAC;IAED,sCAAsC;IACtC,MAAM,CAAC,aAAqB,EAAE,OAAgB,EAAE,IAAW;QACzD,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACzF,CAAC;CACF,CAAC"}
package/dist/mcp.d.ts CHANGED
@@ -19,6 +19,16 @@ export interface McpToolResult {
19
19
  isError?: boolean;
20
20
  [key: string]: unknown;
21
21
  }
22
+ export interface McpInitializeResult {
23
+ protocolVersion: string;
24
+ capabilities: Record<string, unknown>;
25
+ serverInfo: {
26
+ name: string;
27
+ version: string;
28
+ [key: string]: unknown;
29
+ };
30
+ [key: string]: unknown;
31
+ }
22
32
  /**
23
33
  * Thin client for the PingRoom MCP endpoint (`POST /api/agent/mcp`,
24
34
  * JSON-RPC 2.0). Tools are scope-filtered server-side, so `listTools()` returns
@@ -28,13 +38,25 @@ export declare class McpClient {
28
38
  private readonly http;
29
39
  private readonly path;
30
40
  private nextId;
41
+ private initialization;
42
+ private initializeResult;
43
+ private protocolVersion;
31
44
  constructor(http: HttpClient, path?: string);
32
45
  /** Raw JSON-RPC call. Resolves the `result`; throws PingRoomError on a JSON-RPC `error`. */
33
46
  call<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
34
- initialize(params?: Record<string, unknown>): Promise<unknown>;
47
+ /**
48
+ * Perform the MCP initialize handshake once, including the required
49
+ * `notifications/initialized` notification. Safe to call more than once.
50
+ */
51
+ initialize(params?: Record<string, unknown>): Promise<McpInitializeResult>;
52
+ /** Alias for initialize(), useful when treating this helper as a connection. */
53
+ connect(params?: Record<string, unknown>): Promise<McpInitializeResult>;
35
54
  listTools(): Promise<{
36
55
  tools: McpTool[];
37
56
  }>;
38
57
  callTool(name: string, args?: Record<string, unknown>): Promise<McpToolResult>;
58
+ private performInitialize;
59
+ private notify;
60
+ private headers;
39
61
  }
40
62
  //# sourceMappingURL=mcp.d.ts.map
package/dist/mcp.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAAa,SAAS;IAIlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJvB,OAAO,CAAC,MAAM,CAAK;gBAGA,IAAI,EAAE,UAAU,EAChB,IAAI,SAAmB;IAG1C,4FAA4F;IACtF,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAgBrF,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAW9D,SAAS,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAI1C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC;CAGnF"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACtE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAAa,SAAS;IAOlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPvB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,gBAAgB,CAAoC;IAC5D,OAAO,CAAC,eAAe,CAAuB;gBAG3B,IAAI,EAAE,UAAU,EAChB,IAAI,SAAmB;IAG1C,4FAA4F;IACtF,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAgBrF;;;OAGG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAc1E,gFAAgF;IAChF,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAIjE,SAAS,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IAK1C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAK1E,iBAAiB;YAsBjB,MAAM;IAQpB,OAAO,CAAC,OAAO;CAMhB"}
package/dist/mcp.js CHANGED
@@ -9,6 +9,9 @@ export class McpClient {
9
9
  http;
10
10
  path;
11
11
  nextId = 1;
12
+ initialization = null;
13
+ initializeResult = null;
14
+ protocolVersion = null;
12
15
  constructor(http, path = '/api/agent/mcp') {
13
16
  this.http = http;
14
17
  this.path = path;
@@ -19,7 +22,7 @@ export class McpClient {
19
22
  const envelope = { jsonrpc: '2.0', id, method, ...(params ? { params } : {}) };
20
23
  const res = await this.http.request('POST', this.path, {
21
24
  body: envelope,
22
- headers: { Accept: 'application/json, text/event-stream' },
25
+ headers: this.headers(),
23
26
  });
24
27
  if (res && res.error) {
25
28
  throw new PingRoomError(`MCP error ${res.error.code}: ${res.error.message}`, {
@@ -29,18 +32,63 @@ export class McpClient {
29
32
  }
30
33
  return res?.result;
31
34
  }
35
+ /**
36
+ * Perform the MCP initialize handshake once, including the required
37
+ * `notifications/initialized` notification. Safe to call more than once.
38
+ */
32
39
  initialize(params) {
33
- return this.call('initialize', params ?? {
40
+ if (this.initializeResult) {
41
+ return Promise.resolve(this.initializeResult);
42
+ }
43
+ if (this.initialization) {
44
+ return this.initialization;
45
+ }
46
+ this.initialization = this.performInitialize(params).finally(() => {
47
+ this.initialization = null;
48
+ });
49
+ return this.initialization;
50
+ }
51
+ /** Alias for initialize(), useful when treating this helper as a connection. */
52
+ connect(params) {
53
+ return this.initialize(params);
54
+ }
55
+ async listTools() {
56
+ await this.initialize();
57
+ return this.call('tools/list');
58
+ }
59
+ async callTool(name, args = {}) {
60
+ await this.initialize();
61
+ return this.call('tools/call', { name, arguments: args });
62
+ }
63
+ async performInitialize(params) {
64
+ const result = await this.call('initialize', params ?? {
34
65
  protocolVersion: '2025-06-18',
35
66
  capabilities: {},
36
67
  clientInfo: { name: 'pingroom-sdk', version: VERSION },
37
68
  });
69
+ if (!result || typeof result.protocolVersion !== 'string') {
70
+ throw new PingRoomError('MCP initialize response did not include a protocol version.', {
71
+ code: 'mcp_invalid_initialize',
72
+ body: result,
73
+ });
74
+ }
75
+ this.protocolVersion = result.protocolVersion;
76
+ await this.notify('notifications/initialized');
77
+ this.initializeResult = result;
78
+ return result;
38
79
  }
39
- listTools() {
40
- return this.call('tools/list');
80
+ async notify(method, params) {
81
+ const envelope = { jsonrpc: '2.0', method, ...(params ? { params } : {}) };
82
+ await this.http.request('POST', this.path, {
83
+ body: envelope,
84
+ headers: this.headers(),
85
+ });
41
86
  }
42
- callTool(name, args = {}) {
43
- return this.call('tools/call', { name, arguments: args });
87
+ headers() {
88
+ return {
89
+ Accept: 'application/json, text/event-stream',
90
+ ...(this.protocolVersion ? { 'MCP-Protocol-Version': this.protocolVersion } : {}),
91
+ };
44
92
  }
45
93
  }
46
94
  //# sourceMappingURL=mcp.js.map
package/dist/mcp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAqBvC;;;;GAIG;AACH,MAAM,OAAO,SAAS;IAID;IACA;IAJX,MAAM,GAAG,CAAC,CAAC;IAEnB,YACmB,IAAgB,EAChB,OAAO,gBAAgB;QADvB,SAAI,GAAJ,IAAI,CAAY;QAChB,SAAI,GAAJ,IAAI,CAAmB;IACvC,CAAC;IAEJ,4FAA4F;IAC5F,KAAK,CAAC,IAAI,CAAc,MAAc,EAAE,MAAgC;QACtE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/E,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAuC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE;YAC3F,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE,MAAM,EAAE,qCAAqC,EAAE;SAC3D,CAAC,CAAC;QACH,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,IAAI,aAAa,CAAC,aAAa,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE;gBAC3E,IAAI,EAAE,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;gBAC7B,IAAI,EAAE,GAAG,CAAC,KAAK;aAChB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,GAAG,EAAE,MAAW,CAAC;IAC1B,CAAC;IAED,UAAU,CAAC,MAAgC;QACzC,OAAO,IAAI,CAAC,IAAI,CACd,YAAY,EACZ,MAAM,IAAI;YACR,eAAe,EAAE,YAAY;YAC7B,YAAY,EAAE,EAAE;YAChB,UAAU,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE;SACvD,CACF,CAAC;IACJ,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,IAAI,CAAuB,YAAY,CAAC,CAAC;IACvD,CAAC;IAED,QAAQ,CAAC,IAAY,EAAE,OAAgC,EAAE;QACvD,OAAO,IAAI,CAAC,IAAI,CAAgB,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;CACF"}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}