@unboundai/tb-ppt-mgagent 0.1.0 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +26 -4
  2. package/build/index.js +19 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -15,7 +15,9 @@ Built against the official Managed Agents docs (session creation, session operat
15
15
 
16
16
  ## What's still an assumption
17
17
 
18
- Everything above matches the documented API and SDK method signatures verbatim (verified against platform.claude.com/docs/en/managed-agents/\* while building this). The one thing **not** confirmed against a real response is the exact `filename`/path convention the Files API returns for a file the agent wrote to its outputs directory — the code guesses by matching `/outputs?[\/]/i` against the filename and falling back to any `.pptx` file on the session if nothing matches that pattern. If a real run's file list looks different, adjust the filter in `get_tb_powerpoint_result` in `src/index.ts`.
18
+ Every SDK call in `src/index.ts` (`sessions.create`, `sessions.events.send`, `sessions.retrieve`, `sessions.events.list`, `files.list`, `files.download`) is checked against `@anthropic-ai/sdk`'s own `.d.ts`/source (installed version, not just the docs prose) — that's how a real bug was caught in 0.1.0: the docs' TypeScript sample for downloading a file shows `content.writeToFile(path)`, but that method doesn't exist on the installed SDK. `files.download()` actually resolves to a plain `Response`; 0.1.1 fixes this by reading it with `.arrayBuffer()` and writing the bytes directly.
19
+
20
+ The one thing still **not** confirmed against a real response is the exact `filename`/path convention the Files API returns for a file the agent wrote to its outputs directory — the code guesses by matching `/outputs?[\/]/i` against the filename and falling back to any `.pptx` file on the session if nothing matches that pattern. If a real run's file list looks different, adjust the filter in `get_tb_powerpoint_result` in `src/index.ts`.
19
21
 
20
22
  ## Setup
21
23
 
@@ -37,13 +39,14 @@ Everything above matches the documented API and SDK method signatures verbatim (
37
39
  - `TB_PPT_OUTPUT_DIR` — required for `get_tb_powerpoint_result`. Local folder that's synced to GCS by something outside this server; finished `.pptx` files are written here.
38
40
  - `TB_PPT_PUBLIC_URL_BASE` — required for `get_tb_powerpoint_result`. Base URL the synced folder is served from (e.g. `https://storage.googleapis.com/bucket/prefix`), used to build the returned download link.
39
41
 
40
- 4. **Register with your MCP client** (Claude Desktop / TypingMind's local MCP connector — same pattern as this repo's siblings, e.g. `tb-gcs-assembly-mcp`):
42
+ 4. **Register with your MCP client** (Claude Desktop / TypingMind's local MCP connector — same pattern as this repo's siblings, e.g. `tb-gcs-assembly-mcp`). Published to npm as [`@unboundai/tb-ppt-mgagent`](https://www.npmjs.com/package/@unboundai/tb-ppt-mgagent), so `npx` can run it without a local checkout:
41
43
 
42
44
  ```json
43
45
  "tb-ppt-mgagent": {
44
- "command": "node",
46
+ "command": "npx",
45
47
  "args": [
46
- "/path/to/tb-ppt-mgAgent/build/index.js"
48
+ "-y",
49
+ "@unboundai/tb-ppt-mgagent"
47
50
  ],
48
51
  "env": {
49
52
  "ANTHROPIC_API_KEY": "sk-ant-...",
@@ -55,6 +58,25 @@ Everything above matches the documented API and SDK method signatures verbatim (
55
58
  }
56
59
  ```
57
60
 
61
+ Or, from a local checkout of this repo:
62
+
63
+ ```json
64
+ "tb-ppt-mgagent": {
65
+ "command": "node",
66
+ "args": [
67
+ "/path/to/tb-ppt-mgAgent/build/index.js"
68
+ ],
69
+ "env": { "...": "same as above" }
70
+ }
71
+ ```
72
+
73
+ ### Publishing a new version
74
+
75
+ ```bash
76
+ npm version patch # or minor/major
77
+ npm publish # prepublishOnly rebuilds automatically; will prompt for a 2FA OTP
78
+ ```
79
+
58
80
  ## Development
59
81
 
60
82
  ```bash
package/build/index.js CHANGED
@@ -19,11 +19,13 @@
19
19
  * automatically for session endpoints. The Files API additionally takes an
20
20
  * explicit `betas` array on list/download, per the docs' own example.
21
21
  *
22
- * A couple of the beta SDK's exact TypeScript types for newer event/file
23
- * fields (stop_reason, processed_at, filename) aren't fully pinned down
24
- * here - those spots are narrowed with `as any` and a comment rather than
25
- * guessed field names baked into strict types, so a real API response can't
26
- * silently mismatch a wrong compile-time shape.
22
+ * Every call here is checked against @anthropic-ai/sdk's own .d.ts/source
23
+ * (v0.120.0, the latest published at the time of writing) rather than taken
24
+ * on faith from the docs prose - the docs' TypeScript sample for downloading
25
+ * a file shows `content.writeToFile(path)`, but that method does not exist
26
+ * on the installed SDK: `files.download()` resolves to a plain `Response`,
27
+ * read with `.arrayBuffer()` below. If a future SDK version reintroduces a
28
+ * writeToFile-style helper, this can simplify back down.
27
29
  *
28
30
  * Environment variables:
29
31
  * - ANTHROPIC_API_KEY: required. Anthropic API key with Managed Agents access.
@@ -218,16 +220,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
218
220
  };
219
221
  }
220
222
  // Find the most recent session.status_idle event to read its stop_reason.
221
- // (Its exact field shape isn't pinned down in our TS types yet - see file header.)
222
223
  let latestIdleEvent = null;
223
224
  for await (const event of client.beta.sessions.events.list(sessionId)) {
224
225
  if (event.type === "session.status_idle") {
225
- if (!latestIdleEvent || (event.processed_at ?? "") > (latestIdleEvent.processed_at ?? "")) {
226
+ if (!latestIdleEvent || event.processed_at > latestIdleEvent.processed_at) {
226
227
  latestIdleEvent = event;
227
228
  }
228
229
  }
229
230
  }
230
- const stopReasonType = latestIdleEvent?.stop_reason?.type;
231
+ const stopReasonType = latestIdleEvent?.stop_reason.type;
231
232
  if (stopReasonType !== "end_turn") {
232
233
  return {
233
234
  content: [{
@@ -246,9 +247,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
246
247
  scope_id: sessionId,
247
248
  betas: [MANAGED_AGENTS_BETA]
248
249
  });
249
- const fileList = files.data ?? [];
250
- const pptxFiles = fileList.filter((f) => /\.pptx$/i.test(f.filename ?? ""));
251
- const outputPptxFiles = pptxFiles.filter((f) => /outputs?[\\/]/i.test(f.filename ?? ""));
250
+ const fileList = files.data;
251
+ const pptxFiles = fileList.filter((f) => /\.pptx$/i.test(f.filename));
252
+ const outputPptxFiles = pptxFiles.filter((f) => /outputs?[\\/]/i.test(f.filename));
252
253
  const chosen = outputPptxFiles[0] ?? pptxFiles[0];
253
254
  if (!chosen) {
254
255
  return {
@@ -267,9 +268,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
267
268
  const { outputDir, publicUrlBase } = requireOutputConfig();
268
269
  const safeName = path.basename(chosen.filename || `${sessionId}.pptx`);
269
270
  const destPath = path.join(outputDir, safeName);
271
+ // files.download() resolves to a plain Response on this SDK version - no
272
+ // writeToFile() helper (see file header). Read the bytes and write them ourselves.
273
+ const response = await client.beta.files.download(chosen.id, {
274
+ betas: [MANAGED_AGENTS_BETA]
275
+ });
276
+ const arrayBuffer = await response.arrayBuffer();
270
277
  fs.mkdirSync(outputDir, { recursive: true });
271
- const content = await client.beta.files.download(chosen.id);
272
- await content.writeToFile(destPath);
278
+ fs.writeFileSync(destPath, Buffer.from(arrayBuffer));
273
279
  const downloadUrl = `${publicUrlBase.replace(/\/$/, "")}/${encodeURIComponent(safeName)}`;
274
280
  return {
275
281
  content: [{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundai/tb-ppt-mgagent",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "MCP server that hands a presentation outline to the Traffic Builders PowerPoint Managed Agent, then retrieves the finished .pptx",
5
5
  "main": "build/index.js",
6
6
  "bin": {