@sync.so/mcp-server 0.1.3 → 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 (261) hide show
  1. package/README.md +261 -86
  2. package/deploy/generation-status/app.html.gz +0 -0
  3. package/deploy/generation-status/release.json +6 -0
  4. package/dist/abort-signals.d.ts +6 -0
  5. package/dist/abort-signals.d.ts.map +1 -0
  6. package/dist/abort-signals.js +23 -0
  7. package/dist/account-features.d.ts +7 -0
  8. package/dist/account-features.d.ts.map +1 -0
  9. package/dist/account-features.js +48 -0
  10. package/dist/app-upload-relay.d.ts +13 -0
  11. package/dist/app-upload-relay.d.ts.map +1 -0
  12. package/dist/app-upload-relay.js +136 -0
  13. package/dist/asset-thumbnail.d.ts +3 -0
  14. package/dist/asset-thumbnail.d.ts.map +1 -0
  15. package/dist/asset-thumbnail.js +2 -0
  16. package/dist/auth/async-context.d.ts +5 -0
  17. package/dist/auth/async-context.d.ts.map +1 -0
  18. package/dist/auth/async-context.js +14 -0
  19. package/dist/auth/bearer-auth.d.ts +16 -0
  20. package/dist/auth/bearer-auth.d.ts.map +1 -0
  21. package/dist/auth/bearer-auth.js +55 -0
  22. package/dist/auth/client-credentials.d.ts +13 -0
  23. package/dist/auth/client-credentials.d.ts.map +1 -0
  24. package/dist/auth/client-credentials.js +67 -0
  25. package/dist/auth/device-auth.d.ts.map +1 -1
  26. package/dist/auth/device-auth.js +3 -2
  27. package/dist/auth/fixture-cleanup.d.ts +4 -0
  28. package/dist/auth/fixture-cleanup.d.ts.map +1 -0
  29. package/dist/auth/fixture-cleanup.js +9 -0
  30. package/dist/auth/index.d.ts +2 -0
  31. package/dist/auth/index.d.ts.map +1 -1
  32. package/dist/auth/index.js +2 -0
  33. package/dist/auth/oauth-diagnostics.d.ts +11 -0
  34. package/dist/auth/oauth-diagnostics.d.ts.map +1 -0
  35. package/dist/auth/oauth-diagnostics.js +78 -0
  36. package/dist/auth/oauth-provider.d.ts +16 -0
  37. package/dist/auth/oauth-provider.d.ts.map +1 -0
  38. package/dist/auth/oauth-provider.js +107 -0
  39. package/dist/auth/resource-metadata.d.ts +2 -0
  40. package/dist/auth/resource-metadata.d.ts.map +1 -0
  41. package/dist/auth/resource-metadata.js +3 -0
  42. package/dist/auth/token-verification.d.ts +11 -0
  43. package/dist/auth/token-verification.d.ts.map +1 -0
  44. package/dist/auth/token-verification.js +99 -0
  45. package/dist/auth/verification-cache.d.ts +8 -0
  46. package/dist/auth/verification-cache.d.ts.map +1 -0
  47. package/dist/auth/verification-cache.js +111 -0
  48. package/dist/chatgpt-analytics.d.ts +22 -0
  49. package/dist/chatgpt-analytics.d.ts.map +1 -0
  50. package/dist/chatgpt-analytics.js +172 -0
  51. package/dist/chatgpt-app.d.ts +15 -0
  52. package/dist/chatgpt-app.d.ts.map +1 -0
  53. package/dist/chatgpt-app.js +133 -0
  54. package/dist/chatgpt-release.d.ts +12 -0
  55. package/dist/chatgpt-release.d.ts.map +1 -0
  56. package/dist/chatgpt-release.js +30 -0
  57. package/dist/cli.js +30 -16
  58. package/dist/client-profile.d.ts +10 -0
  59. package/dist/client-profile.d.ts.map +1 -0
  60. package/dist/client-profile.js +45 -0
  61. package/dist/config.d.ts +17 -0
  62. package/dist/config.d.ts.map +1 -1
  63. package/dist/config.js +52 -0
  64. package/dist/generation-status-html.d.ts +2 -0
  65. package/dist/generation-status-html.d.ts.map +1 -0
  66. package/dist/generation-status-html.js +26 -0
  67. package/dist/generation-status.d.ts +6 -0
  68. package/dist/generation-status.d.ts.map +1 -0
  69. package/dist/generation-status.js +37 -0
  70. package/dist/http-client.d.ts +45 -1
  71. package/dist/http-client.d.ts.map +1 -1
  72. package/dist/http-client.js +171 -34
  73. package/dist/http-server.d.ts +53 -0
  74. package/dist/http-server.d.ts.map +1 -0
  75. package/dist/http-server.js +753 -0
  76. package/dist/http-session.d.ts +18 -0
  77. package/dist/http-session.d.ts.map +1 -0
  78. package/dist/http-session.js +189 -0
  79. package/dist/index.d.ts +4 -3
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +3 -2
  82. package/dist/oauth-response.d.ts +3 -0
  83. package/dist/oauth-response.d.ts.map +1 -0
  84. package/dist/oauth-response.js +30 -0
  85. package/dist/openapi/index.d.ts +2 -2
  86. package/dist/openapi/index.d.ts.map +1 -1
  87. package/dist/openapi/index.js +1 -1
  88. package/dist/openapi/parser.d.ts +2 -0
  89. package/dist/openapi/parser.d.ts.map +1 -1
  90. package/dist/openapi/parser.js +41 -1
  91. package/dist/openapi/types.d.ts +3 -0
  92. package/dist/openapi/types.d.ts.map +1 -1
  93. package/dist/organization-selection.d.ts +61 -0
  94. package/dist/organization-selection.d.ts.map +1 -0
  95. package/dist/organization-selection.js +142 -0
  96. package/dist/rate-limits.d.ts +13 -0
  97. package/dist/rate-limits.d.ts.map +1 -0
  98. package/dist/rate-limits.js +67 -0
  99. package/dist/revision.d.ts +6 -0
  100. package/dist/revision.d.ts.map +1 -0
  101. package/dist/revision.js +17 -0
  102. package/dist/runtime-diagnostics.d.ts +32 -0
  103. package/dist/runtime-diagnostics.d.ts.map +1 -0
  104. package/dist/runtime-diagnostics.js +58 -0
  105. package/dist/server.d.ts +23 -2
  106. package/dist/server.d.ts.map +1 -1
  107. package/dist/server.js +893 -32
  108. package/dist/session-registry.d.ts +54 -0
  109. package/dist/session-registry.d.ts.map +1 -0
  110. package/dist/session-registry.js +202 -0
  111. package/dist/session-telemetry.d.ts +13 -0
  112. package/dist/session-telemetry.d.ts.map +1 -0
  113. package/dist/session-telemetry.js +87 -0
  114. package/dist/spend-confirmation.d.ts +21 -0
  115. package/dist/spend-confirmation.d.ts.map +1 -0
  116. package/dist/spend-confirmation.js +105 -0
  117. package/dist/tool-analytics-context.d.ts +11 -0
  118. package/dist/tool-analytics-context.d.ts.map +1 -0
  119. package/dist/tool-analytics-context.js +8 -0
  120. package/dist/tool-names.d.ts +35 -0
  121. package/dist/tool-names.d.ts.map +1 -0
  122. package/dist/tool-names.js +133 -0
  123. package/dist/tools/account-context.d.ts +5 -0
  124. package/dist/tools/account-context.d.ts.map +1 -0
  125. package/dist/tools/account-context.js +131 -0
  126. package/dist/tools/account-management.d.ts +4 -0
  127. package/dist/tools/account-management.d.ts.map +1 -0
  128. package/dist/tools/account-management.js +111 -0
  129. package/dist/tools/app-tools.d.ts +31 -0
  130. package/dist/tools/app-tools.d.ts.map +1 -0
  131. package/dist/tools/app-tools.js +350 -0
  132. package/dist/tools/asset-analysis.d.ts +4 -0
  133. package/dist/tools/asset-analysis.d.ts.map +1 -0
  134. package/dist/tools/asset-analysis.js +172 -0
  135. package/dist/tools/asset-creators.d.ts +4 -0
  136. package/dist/tools/asset-creators.d.ts.map +1 -0
  137. package/dist/tools/asset-creators.js +38 -0
  138. package/dist/tools/audio-trim.d.ts +6 -0
  139. package/dist/tools/audio-trim.d.ts.map +1 -0
  140. package/dist/tools/audio-trim.js +79 -0
  141. package/dist/tools/batch-results.d.ts +16 -0
  142. package/dist/tools/batch-results.d.ts.map +1 -0
  143. package/dist/tools/batch-results.js +103 -0
  144. package/dist/tools/batches.d.ts +28 -0
  145. package/dist/tools/batches.d.ts.map +1 -0
  146. package/dist/tools/batches.js +293 -0
  147. package/dist/tools/dialogue.d.ts +6 -0
  148. package/dist/tools/dialogue.d.ts.map +1 -0
  149. package/dist/tools/dialogue.js +309 -0
  150. package/dist/tools/estimate-duration.d.ts +35 -0
  151. package/dist/tools/estimate-duration.d.ts.map +1 -0
  152. package/dist/tools/estimate-duration.js +66 -0
  153. package/dist/tools/feedback.d.ts +14 -0
  154. package/dist/tools/feedback.d.ts.map +1 -0
  155. package/dist/tools/feedback.js +72 -0
  156. package/dist/tools/generated-adapters.d.ts +25 -0
  157. package/dist/tools/generated-adapters.d.ts.map +1 -0
  158. package/dist/tools/generated-adapters.js +143 -0
  159. package/dist/tools/generation-context.d.ts +14 -0
  160. package/dist/tools/generation-context.d.ts.map +1 -0
  161. package/dist/tools/generation-context.js +39 -0
  162. package/dist/tools/generation-continuation.d.ts +4 -0
  163. package/dist/tools/generation-continuation.d.ts.map +1 -0
  164. package/dist/tools/generation-continuation.js +124 -0
  165. package/dist/tools/generation-costs.d.ts +6 -0
  166. package/dist/tools/generation-costs.d.ts.map +1 -0
  167. package/dist/tools/generation-costs.js +67 -0
  168. package/dist/tools/generation-output.d.ts +3 -0
  169. package/dist/tools/generation-output.d.ts.map +1 -0
  170. package/dist/tools/generation-output.js +39 -0
  171. package/dist/tools/generator.d.ts +35 -2
  172. package/dist/tools/generator.d.ts.map +1 -1
  173. package/dist/tools/generator.js +127 -9
  174. package/dist/tools/job-status.d.ts +35 -0
  175. package/dist/tools/job-status.d.ts.map +1 -0
  176. package/dist/tools/job-status.js +92 -0
  177. package/dist/tools/job-wait.d.ts +41 -0
  178. package/dist/tools/job-wait.d.ts.map +1 -0
  179. package/dist/tools/job-wait.js +84 -0
  180. package/dist/tools/jobs.d.ts +3 -0
  181. package/dist/tools/jobs.d.ts.map +1 -0
  182. package/dist/tools/jobs.js +210 -0
  183. package/dist/tools/media-upload.d.ts +27 -0
  184. package/dist/tools/media-upload.d.ts.map +1 -0
  185. package/dist/tools/media-upload.js +247 -0
  186. package/dist/tools/model-options.d.ts +36 -0
  187. package/dist/tools/model-options.d.ts.map +1 -0
  188. package/dist/tools/model-options.js +48 -0
  189. package/dist/tools/organization-choice.d.ts +9 -0
  190. package/dist/tools/organization-choice.d.ts.map +1 -0
  191. package/dist/tools/organization-choice.js +136 -0
  192. package/dist/tools/organizations.d.ts +56 -0
  193. package/dist/tools/organizations.d.ts.map +1 -0
  194. package/dist/tools/organizations.js +235 -0
  195. package/dist/tools/output-schemas.d.ts +54 -0
  196. package/dist/tools/output-schemas.d.ts.map +1 -0
  197. package/dist/tools/output-schemas.js +58 -0
  198. package/dist/tools/overrides.d.ts +3 -0
  199. package/dist/tools/overrides.d.ts.map +1 -1
  200. package/dist/tools/overrides.js +113 -15
  201. package/dist/tools/playback-metadata.d.ts +4 -0
  202. package/dist/tools/playback-metadata.d.ts.map +1 -0
  203. package/dist/tools/playback-metadata.js +51 -0
  204. package/dist/tools/project-destination.d.ts +13 -0
  205. package/dist/tools/project-destination.d.ts.map +1 -0
  206. package/dist/tools/project-destination.js +45 -0
  207. package/dist/tools/project-history.d.ts +6 -0
  208. package/dist/tools/project-history.d.ts.map +1 -0
  209. package/dist/tools/project-history.js +45 -0
  210. package/dist/tools/project-intent.d.ts +8 -0
  211. package/dist/tools/project-intent.d.ts.map +1 -0
  212. package/dist/tools/project-intent.js +87 -0
  213. package/dist/tools/running-submissions.d.ts +7 -0
  214. package/dist/tools/running-submissions.d.ts.map +1 -0
  215. package/dist/tools/running-submissions.js +91 -0
  216. package/dist/tools/speech.d.ts +6 -0
  217. package/dist/tools/speech.d.ts.map +1 -0
  218. package/dist/tools/speech.js +116 -0
  219. package/dist/tools/studio-draft.d.ts +7 -0
  220. package/dist/tools/studio-draft.d.ts.map +1 -0
  221. package/dist/tools/studio-draft.js +195 -0
  222. package/dist/tools/studio-view-contract.d.ts +184 -0
  223. package/dist/tools/studio-view-contract.d.ts.map +1 -0
  224. package/dist/tools/studio-view-contract.js +67 -0
  225. package/dist/tools/studio-view.d.ts +6 -0
  226. package/dist/tools/studio-view.d.ts.map +1 -0
  227. package/dist/tools/studio-view.js +126 -0
  228. package/dist/tools/timeline-lipsync.d.ts +316 -0
  229. package/dist/tools/timeline-lipsync.d.ts.map +1 -0
  230. package/dist/tools/timeline-lipsync.js +304 -0
  231. package/dist/tools/translation-preview.d.ts +8 -0
  232. package/dist/tools/translation-preview.d.ts.map +1 -0
  233. package/dist/tools/translation-preview.js +146 -0
  234. package/dist/tools/translation.d.ts +6 -0
  235. package/dist/tools/translation.d.ts.map +1 -0
  236. package/dist/tools/translation.js +131 -0
  237. package/dist/tools/upload-widget.d.ts +13 -0
  238. package/dist/tools/upload-widget.d.ts.map +1 -0
  239. package/dist/tools/upload-widget.js +788 -0
  240. package/dist/toolsets.d.ts +18 -0
  241. package/dist/toolsets.d.ts.map +1 -0
  242. package/dist/toolsets.js +157 -0
  243. package/dist/update-check.d.ts +38 -0
  244. package/dist/update-check.d.ts.map +1 -0
  245. package/dist/update-check.js +150 -0
  246. package/dist/upload-runtime.d.ts +45 -0
  247. package/dist/upload-runtime.d.ts.map +1 -0
  248. package/dist/upload-runtime.js +156 -0
  249. package/dist/upload-source.d.ts +4 -0
  250. package/dist/upload-source.d.ts.map +1 -0
  251. package/dist/upload-source.js +46 -0
  252. package/dist/version.d.ts +2 -0
  253. package/dist/version.d.ts.map +1 -0
  254. package/dist/version.js +3 -0
  255. package/package.json +79 -33
  256. package/dist/openapi/parser.test.d.ts +0 -2
  257. package/dist/openapi/parser.test.d.ts.map +0 -1
  258. package/dist/openapi/parser.test.js +0 -188
  259. package/dist/tools/generator.test.d.ts +0 -2
  260. package/dist/tools/generator.test.d.ts.map +0 -1
  261. package/dist/tools/generator.test.js +0 -178
package/README.md CHANGED
@@ -1,118 +1,222 @@
1
- # Sync MCP Server
1
+ # sync. MCP server
2
2
 
3
- An open-source [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for the [Sync](https://sync.so) API. Gives AI agents — Claude Code, ChatGPT, Cursor, Codex, and any MCP-compatible client — the ability to create lipsync videos, manage assets, check generation status, and more.
3
+ Connect your AI agent to [sync.](https://sync.so) to lip-sync videos, translate
4
+ and dub them into other languages, clone voices, and manage assets and projects
5
+ from a chat or a coding session.
4
6
 
5
- Tools are **auto-generated from the Sync OpenAPI spec** at startup. As new API endpoints ship, they become available to agents automatically — no server update needed.
7
+ sync. hosts this server at **`https://mcp.sync.so/mcp`**. You sign in with your
8
+ sync. account, so there is nothing to install and no API key to copy. Every merge
9
+ to this repository's `main` deploys there.
6
10
 
7
- ## Quick Start
11
+ ## Connect your agent
12
+
13
+ ### ChatGPT
14
+
15
+ Open [sync. in ChatGPT](https://chatgpt.com/plugins/plugin_asdk_app_6a398355fbc08191a232e7eeeacb73d5)
16
+ and connect your account. In ChatGPT, sync. Studio also opens inside the chat.
17
+
18
+ ### Claude (claude.ai and Claude Desktop)
19
+
20
+ 1. Open **Settings → Connectors** and choose **Add custom connector**.
21
+ 2. Name it `sync.` and set the URL to `https://mcp.sync.so/mcp`.
22
+ 3. Click **Connect** and sign in to sync.
8
23
 
9
24
  ### Claude Code
10
25
 
11
26
  ```bash
12
- claude mcp add sync -- npx -y @sync.so/mcp-server --api-key YOUR_API_KEY
27
+ claude mcp add --transport http sync https://mcp.sync.so/mcp
13
28
  ```
14
29
 
15
- Or add to `.mcp.json` in your project root:
30
+ Then run `/mcp` in Claude Code, select `sync` and sign in. Add `--scope user` to
31
+ use it in every project.
16
32
 
17
- ```json
18
- {
19
- "mcpServers": {
20
- "sync": {
21
- "command": "npx",
22
- "args": ["-y", "@sync.so/mcp-server"],
23
- "env": {
24
- "SYNC_API_KEY": "your-api-key"
25
- }
26
- }
27
- }
28
- }
33
+ ### Codex
34
+
35
+ ```bash
36
+ codex mcp add sync --url https://mcp.sync.so/mcp
37
+ codex mcp login sync
29
38
  ```
30
39
 
31
- ### Claude Desktop
40
+ ### Cursor
32
41
 
33
- Add to `claude_desktop_config.json`:
42
+ Add to `.cursor/mcp.json` in a project, or `~/.cursor/mcp.json` for all projects:
34
43
 
35
44
  ```json
36
45
  {
37
46
  "mcpServers": {
38
- "sync": {
39
- "command": "npx",
40
- "args": ["-y", "@sync.so/mcp-server"],
41
- "env": {
42
- "SYNC_API_KEY": "your-api-key"
43
- }
44
- }
47
+ "sync": { "url": "https://mcp.sync.so/mcp" }
45
48
  }
46
49
  }
47
50
  ```
48
51
 
49
- ### Cursor
52
+ Cursor asks you to sign in to sync. the first time it connects.
53
+
54
+ ### VS Code
50
55
 
51
- Add to `.cursor/mcp.json` in your project:
56
+ Add to `.vscode/mcp.json`:
52
57
 
53
58
  ```json
54
59
  {
55
- "mcpServers": {
56
- "sync": {
57
- "command": "npx",
58
- "args": ["-y", "@sync.so/mcp-server"],
59
- "env": {
60
- "SYNC_API_KEY": "your-api-key"
61
- }
62
- }
60
+ "servers": {
61
+ "sync": { "type": "http", "url": "https://mcp.sync.so/mcp" }
63
62
  }
64
63
  }
65
64
  ```
66
65
 
67
- ### Without an API key (interactive login)
66
+ ### Other clients
67
+
68
+ Any client that supports remote MCP servers over Streamable HTTP with OAuth can
69
+ use `https://mcp.sync.so/mcp`. The client registers itself, and you sign in to
70
+ sync. in the browser.
71
+
72
+ The server is listed in the [official MCP Registry](https://registry.modelcontextprotocol.io)
73
+ as `io.github.synchronicity-labs/mcp-server`, so clients and directories that read
74
+ the registry can find and add it. `server.json` is that listing.
68
75
 
69
- Omit `SYNC_API_KEY` and the server will start a device auth flow on first run:
76
+ ### Local server with an API key
77
+
78
+ For clients without remote MCP support, and for scripts and CI, run the server
79
+ locally over stdio with a sync. [API key](https://sync.so/docs/api-reference/guides/authentication):
80
+
81
+ ```bash
82
+ claude mcp add sync -e SYNC_API_KEY=your-api-key -- npx -y @sync.so/mcp-server@latest
83
+ ```
84
+
85
+ Or in a client's JSON config:
70
86
 
71
87
  ```json
72
88
  {
73
89
  "mcpServers": {
74
90
  "sync": {
75
91
  "command": "npx",
76
- "args": ["-y", "@sync.so/mcp-server"]
92
+ "args": ["-y", "@sync.so/mcp-server@latest"],
93
+ "env": { "SYNC_API_KEY": "your-api-key" }
77
94
  }
78
95
  }
79
96
  }
80
97
  ```
81
98
 
82
- You'll be prompted to visit a URL and enter a code. After approval, the token is cached at `~/.config/sync/mcp-credentials.json`.
83
-
84
- ## Getting an API Key
85
-
86
- 1. Sign up at [sync.so](https://sync.so)
87
- 2. Go to your dashboard settings
88
- 3. Generate an API key
89
-
90
- See the [authentication guide](https://sync.so/docs/api-reference/guides/authentication) for details.
99
+ Without `SYNC_API_KEY`, the server starts a device login on first run: visit the
100
+ URL it prints and enter the code. The token is cached at
101
+ `~/.config/sync/mcp-credentials.json`.
102
+
103
+ npm releases are published separately from the hosted deploy and can lag behind
104
+ it, so prefer the hosted server when your client supports it. `@latest` makes npx
105
+ fetch the newest release when the client restarts the server; without it, npx can
106
+ keep running an old cached copy.
107
+
108
+ #### Update notice
109
+
110
+ At startup a local server asks the npm registry for the latest version, at most once
111
+ a day (the answer is cached in `~/.config/sync/mcp-update-check.json`). The check runs
112
+ in the background with a two-second limit and never delays startup or a tool call; if
113
+ it fails, nothing is shown. When a newer version exists, the server's instructions and
114
+ the first tool result of the session tell the agent to ask you to restart with
115
+ `npx -y @sync.so/mcp-server@latest` or switch to the hosted server.
116
+
117
+ To turn it off, set `SYNC_MCP_UPDATE_CHECK=off` or pass `--no-update-check`. It is
118
+ also skipped when `CI` is set, and the hosted server never checks.
119
+
120
+ ## What to ask
121
+
122
+ Paste prompts like these into your agent. Asset IDs come from your sync. library.
123
+ Links can be public media URLs or YouTube, TikTok, Instagram and Facebook videos.
124
+
125
+ | Ask | What the agent does |
126
+ | --- | --- |
127
+ | "Lipsync video asset `<video-asset-id>` with audio asset `<audio-asset-id>`." | `lipsync_create` with the saved assets, then waits for the result |
128
+ | "Lipsync https://example.com/talk.mp4 to https://example.com/voiceover.wav." | `lipsync_create` with public URLs |
129
+ | "Translate https://www.youtube.com/watch?v=… to Spanish." | Imports the link with `assets_create`, quotes the cost, and after you confirm runs `dubbing_create` |
130
+ | "Make video asset `<video-asset-id>` say “thanks for watching” in a calm narrator voice." | Picks a voice with `voices_list`, quotes the script, then `lipsync_create` with `script` |
131
+ | "How many credits do I have left?" | `account_get-usage` |
132
+ | "What did my last generation cost?" | Finds it in history and reads `generations_get-costs` |
133
+
134
+ Translation, dubbing, speech previews and voice clones are quoted and confirmed
135
+ with you before they start.
136
+
137
+ ### Agent skills
138
+
139
+ Step-by-step workflows for these tools (lipsync, talking photos, dubbing, Edit Dialogue,
140
+ campaigns, batches, troubleshooting and the API) are agent skills in
141
+ [synchronicity-labs/skills](https://github.com/synchronicity-labs/skills). Install them
142
+ in any agent with `npx skills add synchronicity-labs/skills`. The ChatGPT and Codex
143
+ plugin ships them from a pinned commit of that repository; see
144
+ [docs/chatgpt-plugin.md](docs/chatgpt-plugin.md).
145
+
146
+ ## Tools
147
+
148
+ The hosted server exposes a curated set of tools to every client:
149
+
150
+ | Area | Tools |
151
+ | --- | --- |
152
+ | Lip sync | `lipsync_create`, `lipsync_create-timeline`¹, `generations_estimate-cost`, `generations_get`, `generations_list`, `generations_get-continuation`, `generations_get-costs`, `models_list` |
153
+ | Translation and dubbing | `dubbing_create`, `dubbing_get-options`, `translation-previews_estimate`, `translation-previews_create`, `translation-previews_get` |
154
+ | Speech and voices | `speech-previews_create`, `speech-previews_get-options`, `speech-previews_get`, `voices_list`, `voices_clone` |
155
+ | Edit Dialogue | `dialogue_get-options`, `dialogue_upload-source`, `dialogue-transcriptions_create`, `dialogue-transcriptions_get`, `dialogue-previews_create`, `dialogue-previews_get`, `dialogue-videos_estimate`, `dialogue-videos_create` |
156
+ | Assets | `assets_create`, `assets_create-upload-url`, `assets_get`, `assets_list`, `assets_count`, `assets_get-download-url`, `assets_update`, `assets_delete`, `assets_get-playback-metadata`, `audio-trims_get`, `audio-trims_create` |
157
+ | Projects | `projects_create`, `projects_get`, `projects_list`, `projects_list-generations`, `projects_rename` |
158
+ | Batches | `batches_create`², `batches_get`², `batches_list`² |
159
+ | Account | `account_get-context`, `account_get-usage`, `organizations_list`, `organizations_select` |
160
+
161
+ ¹ Not offered to the ChatGPT app, whose embedded Studio has no timeline.
162
+
163
+ ² Not in the ChatGPT app listing yet. A batch runs 20 or more independent generations
164
+ (500 per batch by default), such as one campaign video localized into many languages.
165
+ Where the account's plan doesn't include batch, the API answers 402 with `requiredPlan`
166
+ and `billingUrl`, which the tools pass on.
167
+
168
+ Organizations with the matching feature also get `scenes_detect` (camera cuts in a
169
+ video) and `stems_separate` (vocals and background audio), outside the ChatGPT
170
+ app. They are in the `lipsync` and `assets` toolsets locally.
171
+
172
+ Clients with app support also get the tools behind the embedded Studio app:
173
+ Studio views and drafts, the upload widget and app helpers. Those are clients
174
+ whose MCP handshake name selects the ChatGPT or Codex app profile (`openai-mcp`,
175
+ `openai-mcp (Codex)`; see `src/client-profile.ts`). Other clients don't see these
176
+ tools, and their calls to them are refused.
177
+
178
+ ### Local toolsets
179
+
180
+ The local stdio server can also offer a tool for every other public API operation in
181
+ the [OpenAPI spec](https://api.sync.so/api-json), 65+ in all. By default it lists the
182
+ hosted set above, without its admin tools (`assets_delete` and `voices_clone`),
183
+ plus `jobs_get` and `jobs_wait` and the `transcriptions_*` tools, whose speaker face
184
+ tracks feed `lipsync_create-timeline` clips.
185
+
186
+ To list more, set `SYNC_MCP_TOOLSETS` or pass `--toolsets` with a comma-separated list:
187
+
188
+ | Toolset | Adds |
189
+ | --- | --- |
190
+ | `default` | The default above, so `default,admin` adds the admin tools to it |
191
+ | `lipsync` | Lip sync, timeline, Edit Dialogue, audio trim and batch tools, plus raw `generate_*`, `generations_*` and `dialogue-edits_*` |
192
+ | `dubbing` | Translation and dubbing tools, and the batch tools |
193
+ | `assets` | `assets_*` (except deletes) and the upload tools |
194
+ | `projects` | `projects_*` (except deletes) and `projects_rename` |
195
+ | `transcription` | `transcriptions_*` |
196
+ | `voices` | `voices_*` (except cloning and deletes), speech previews and `tts_*` |
197
+ | `admin` | Every delete (`assets_delete`, `projects_delete`, `generations_delete`, `voices_delete`) and `voices_clone` |
198
+ | `all` | Every tool, as before this option existed |
199
+
200
+ Job, account and generation reads (`jobs_get`, `jobs_wait`, `generations_get`,
201
+ `account_get-context`, `organizations_list`, `organizations_select` and similar) come with
202
+ every selection. Naming toolsets replaces
203
+ the default rather than adding to it. To get every tool back:
91
204
 
92
- ## Available Tools
93
-
94
- Tools are dynamically generated from the Sync API. Core tools include:
95
-
96
- | Tool | Description |
97
- |------|-------------|
98
- | `generate_create-generation` | Create a lipsync video from video + audio inputs |
99
- | `generate_get-generation` | Get generation status — poll until COMPLETED |
100
- | `models_get-public` | List available lipsync models |
101
- | `assets_get-all` | List all assets in your organization |
102
- | `assets_get` | Get a specific asset by ID |
103
- | `generations_estimate` | Estimate generation cost before creating |
104
-
105
- Plus every other public endpoint in the [Sync API](https://sync.so/docs/api-reference).
205
+ ```bash
206
+ claude mcp add sync -e SYNC_API_KEY=your-api-key -e SYNC_MCP_TOOLSETS=all -- npx -y @sync.so/mcp-server@latest
207
+ ```
106
208
 
107
- ## Example Prompts
209
+ Unless it lists everything, the server's instructions tell the agent which toolsets are
210
+ listed and how to get the rest, so it can ask you to restart the server with a wider
211
+ set. The hosted server ignores this setting.
108
212
 
109
- Once configured, ask your AI agent:
213
+ [Tool workflows](docs/tool-workflows.md) describes how the multi-step and paid
214
+ tools behave.
110
215
 
111
- - *"List available Sync models"*
112
- - *"Create a lipsync video with this video URL and audio URL using the lipsync-2 model"*
113
- - *"Check the status of generation gen-abc123"*
114
- - *"Show me my recent generations"*
115
- - *"How much would it cost to generate a 30-second video?"*
216
+ Tool names follow one `<noun>_<verb>` scheme (`lipsync_create`, `generations_get`).
217
+ The names used before it (`create-lipsync`, `generate_get-generation`) still work for a
218
+ deprecation period: calls through them run the same tool and add a one-line notice
219
+ naming the new one. [Tool names](docs/tool-names.md) has the full old → new table.
116
220
 
117
221
  ## CLI Options
118
222
 
@@ -124,25 +228,51 @@ Options:
124
228
  --base-url <url> API base URL (default: https://api.sync.so)
125
229
  --transport <type> stdio (default) or http
126
230
  --port <port> HTTP port (default: 3002, only with --transport http)
231
+ --no-spend-confirmation
232
+ Unattended automation: drop the cost-quote and confirm-before-paying
233
+ instructions (or set SYNC_MCP_SPEND_CONFIRMATION=off)
234
+ --no-update-check Skip the daily npm check for a newer version (or set
235
+ SYNC_MCP_UPDATE_CHECK=off; skipped when CI is set)
236
+ --toolsets <list> stdio only: comma-separated tools to list (or set SYNC_MCP_TOOLSETS):
237
+ default, lipsync, dubbing, assets, projects, transcription,
238
+ voices, admin or all (default: the hosted set without admin)
127
239
  -h, --help Show this help message
128
240
  ```
129
241
 
130
- ### Environment Variables
242
+ ### Unattended automation
243
+
244
+ By default the tools tell the agent to quote a paid action and wait for the user's
245
+ approval. When the server runs a pipeline or a scheduled agent whose operator has already
246
+ approved spending, start it with `--no-spend-confirmation` (or
247
+ `SYNC_MCP_SPEND_CONFIRMATION=off`). The agent then creates jobs without quoting or asking,
248
+ and estimate tools stay available. Agents cannot change this setting.
131
249
 
132
- | Variable | Description | Default |
133
- |----------|-------------|---------|
134
- | `SYNC_API_KEY` | Your Sync API key | — |
135
- | `SYNC_BASE_URL` | API base URL | `https://api.sync.so` |
250
+ Job tools take `wait: true` to wait on the server (up to about 50 seconds per call, with
251
+ progress notifications when the client sends a `progressToken`): `generations_get`,
252
+ `translation-previews_get`, `transcriptions_get` and social imports
253
+ through `assets_create`. On the local server, `jobs_wait` and `jobs_get` do the same for
254
+ every kind of job (generation, transcription, speaker analysis, translation preview,
255
+ import) with one input, `{kind, id, projectId?}`, and one result shape and status set;
256
+ see [Jobs](docs/jobs.md).
257
+
258
+ When the API offers it, `feedback_send` lets agents report confusing errors, wrong results
259
+ and missing capabilities to the Sync team.
260
+
261
+ Environment variables and the HTTP server's session, memory, upload and
262
+ diagnostics limits are in [HTTP server configuration](docs/http-server.md).
136
263
 
137
264
  ## How It Works
138
265
 
139
- 1. On startup, the server fetches the OpenAPI spec from `{baseUrl}/api-json`
140
- 2. Parses all public endpoints into operation definitions
141
- 3. Converts each operation into an MCP tool with a Zod input schema
142
- 4. Registers tools on the MCP server
143
- 5. Each tool call makes an authenticated HTTP request to the Sync API
266
+ 1. At startup, the server fetches the public OpenAPI spec from `{baseUrl}/api-json`
267
+ and turns each operation into an MCP tool with a Zod input schema.
268
+ 2. Hand-written tools add multi-step workflows on the same API, such as translate
269
+ and dub, Edit Dialogue, speech previews and cost lookups.
270
+ 3. Each tool call is an authenticated request to the sync. API, with your OAuth
271
+ token (hosted) or API key (local).
144
272
 
145
- This means **new API endpoints are automatically available** — just restart the MCP server.
273
+ Over stdio, a new public API operation becomes a tool on the next restart. The
274
+ hosted server only exposes tools on its allowlist, so a new hosted tool ships with
275
+ a release of this repository.
146
276
 
147
277
  ## Programmatic Usage
148
278
 
@@ -157,25 +287,70 @@ const server = await createSyncMcpServer(config);
157
287
 
158
288
  ## Development
159
289
 
290
+ HTTPS source tests use the local `openssl` command to create a one-day, self-signed
291
+ test identity. Temporary certificate and key files are removed before the tests run.
292
+
160
293
  ```bash
161
294
  # Install dependencies
162
- npm install
295
+ pnpm install
163
296
 
164
297
  # Build
165
- npm run build
298
+ pnpm run build
166
299
 
167
300
  # Run tests
168
- npm test
301
+ pnpm test
169
302
 
170
303
  # Lint
171
- npm run lint
304
+ pnpm run lint
172
305
 
173
306
  # Type check
174
- npm run typecheck
307
+ pnpm run typecheck
308
+
309
+ # Script tests (monitor, smoke check, pre-commit size check)
310
+ pnpm run test:scripts
175
311
  ```
176
312
 
313
+ Development needs Node 26 or newer (`.nvmrc`); `devEngines` in `package.json`
314
+ enforces it on install. `pnpm install` installs a pre-commit hook. It runs Oxlint and Oxfmt on staged
315
+ files, and blocks a staged source file that grows past 5,000 tokens (20,000
316
+ bytes). Files already over that size are exempt until someone splits them.
317
+
318
+ ### Local HTTP Transport Testing
319
+
320
+ To test the HTTP transport (OAuth flow) locally:
321
+
322
+ 1. Copy `.env.example` to `.env` and fill in the values
323
+ 2. Start a tunnel to expose localhost:
324
+ ```bash
325
+ ngrok http 3002
326
+ ```
327
+ 3. Update `MCP_ISSUER_URL` in `.env` with the ngrok URL
328
+ 4. Start the server:
329
+ ```bash
330
+ source .env
331
+ node dist/cli.js --transport http --base-url $SYNC_BASE_URL --port 3002
332
+ ```
333
+ 5. Verify it works:
334
+ ```bash
335
+ curl https://<ngrok-url>/health
336
+ curl https://<ngrok-url>/.well-known/oauth-authorization-server
337
+ ```
338
+ When an isolated Studio login requires the same-origin web proxy, set
339
+ `SYNC_OAUTH_AUTHORIZATION_URL` to its `/api-proxy/v2/oauth/authorize` URL, while
340
+ keeping `SYNC_BASE_URL` on the direct isolated API listener. Only browser
341
+ navigation uses the web proxy. Registration, code exchange, refresh, revocation,
342
+ userinfo and tool calls use the direct API and retain existing deadlines,
343
+ PKCE and confidential-client checks. The optional URL must use HTTP(S), with no
344
+ credentials, query or fragment. Existing deployments need no new setting.
345
+
346
+ 6. Add `https://<ngrok-url>/mcp` as a custom connector in [Claude Web](https://claude.ai)
347
+
177
348
  ## Learn More
178
349
 
350
+ - [Tool workflows](docs/tool-workflows.md) — How multi-step and paid tools behave
351
+ - [HTTP server configuration](docs/http-server.md) — Environment variables and runtime limits
352
+ - [Maintainer notes](docs/maintainers.md) — Hosted compatibility, cancellation, OAuth proxy, uploads and monitoring
353
+ - [Claude directory readiness](docs/claude-directory-readiness.md) — Review checklist and remaining submission work
179
354
  - [Sync Documentation](https://sync.so/docs) — Full API reference and guides
180
355
  - [Sync API Reference](https://sync.so/docs/api-reference) — Endpoint documentation
181
356
  - [MCP Protocol](https://modelcontextprotocol.io) — Learn about the Model Context Protocol
@@ -0,0 +1,6 @@
1
+ {
2
+ "repository": "synchronicity-labs/sync-api-v2",
3
+ "commit": "7128911c4c60a89f43b179510d88d394843084bc",
4
+ "htmlSha256": "b7a9f3ca4342be59c3d037c0fde58668fea441820e9dbf321bc145775ecfe795",
5
+ "htmlBytes": 771668
6
+ }
@@ -0,0 +1,6 @@
1
+ /** Compose cancellation on every supported Node runtime; dispose listeners after work. */
2
+ export declare function combineSignals(signals: AbortSignal[]): {
3
+ signal: AbortSignal;
4
+ dispose: () => void;
5
+ };
6
+ //# sourceMappingURL=abort-signals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort-signals.d.ts","sourceRoot":"","sources":["../src/abort-signals.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG;IACtD,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAoBA"}
@@ -0,0 +1,23 @@
1
+ /** Compose cancellation on every supported Node runtime; dispose listeners after work. */
2
+ export function combineSignals(signals) {
3
+ const controller = new AbortController();
4
+ const listeners = new Map();
5
+ const dispose = () => {
6
+ for (const [signal, listener] of listeners)
7
+ signal.removeEventListener('abort', listener);
8
+ listeners.clear();
9
+ };
10
+ for (const signal of signals) {
11
+ const abort = () => {
12
+ controller.abort(signal.reason);
13
+ dispose();
14
+ };
15
+ if (signal.aborted) {
16
+ abort();
17
+ break;
18
+ }
19
+ listeners.set(signal, abort);
20
+ signal.addEventListener('abort', abort, { once: true });
21
+ }
22
+ return { signal: controller.signal, dispose };
23
+ }
@@ -0,0 +1,7 @@
1
+ import type { Tool } from '@modelcontextprotocol/server';
2
+ import type { HttpClient } from './http-client.js';
3
+ import { type OrganizationSession } from './organization-selection.js';
4
+ export declare function isFeatureGatedTool(name: string): boolean;
5
+ /** The descriptors this organization may see; reads features only when a gated tool is listed. */
6
+ export declare function listedForAccount(descriptors: Tool[], session: OrganizationSession, http: HttpClient): Promise<Tool[]>;
7
+ //# sourceMappingURL=account-features.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-features.d.ts","sourceRoot":"","sources":["../src/account-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,KAAK,mBAAmB,EAA4B,MAAM,6BAA6B,CAAC;AAcjG,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAmCD,kGAAkG;AAClG,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,IAAI,EAAE,EACnB,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,IAAI,EAAE,CAAC,CAMjB"}
@@ -0,0 +1,48 @@
1
+ import { runInOrganizationSession } from './organization-selection.js';
2
+ import { parseAccountOverview } from './tools/organizations.js';
3
+ /**
4
+ * Tools listed only when the active organization's GET /v2/account `features` names the
5
+ * feature: their API routes are behind server-side flags, so other accounts would only get a
6
+ * 404. A tool call is not refused here; the API stays the authority, and the tool reports
7
+ * its 404.
8
+ */
9
+ const TOOL_FEATURES = {
10
+ scenes_detect: 'scene_detection',
11
+ stems_separate: 'stem_separation',
12
+ };
13
+ export function isFeatureGatedTool(name) {
14
+ return Object.hasOwn(TOOL_FEATURES, name);
15
+ }
16
+ // tools/list waits on this read, so it must not take the API's full request budget.
17
+ const FEATURES_TIMEOUT_MS = 5_000;
18
+ /**
19
+ * The active organization's features, kept on the MCP session's OrganizationSession: the
20
+ * stdio process, or one hosted session. organizations_select and account_get-context write
21
+ * the same field when they read the account, so an organization switch changes what is
22
+ * listed. An API without the field means none. A failed read lists no gated tools and keeps
23
+ * nothing, so a later list reads again.
24
+ */
25
+ async function sessionFeatures(session, http) {
26
+ const kept = session.activeFeatures();
27
+ if (kept)
28
+ return new Set(kept);
29
+ const stamp = session.featureStamp();
30
+ try {
31
+ // In the session, so the read names its selected organization like any other call.
32
+ const overview = parseAccountOverview(await runInOrganizationSession(session, () => http.request('get', '/v2/account', { signal: AbortSignal.timeout(FEATURES_TIMEOUT_MS) })));
33
+ const features = overview.features ?? [];
34
+ // Not kept if the session switched meanwhile or the answer is for another organization.
35
+ session.recordFeatures(features, stamp, overview.organization?.id);
36
+ return new Set(features);
37
+ }
38
+ catch {
39
+ return new Set();
40
+ }
41
+ }
42
+ /** The descriptors this organization may see; reads features only when a gated tool is listed. */
43
+ export async function listedForAccount(descriptors, session, http) {
44
+ if (!descriptors.some((tool) => isFeatureGatedTool(tool.name)))
45
+ return descriptors;
46
+ const enabled = await sessionFeatures(session, http);
47
+ return descriptors.filter((tool) => !isFeatureGatedTool(tool.name) || enabled.has(TOOL_FEATURES[tool.name]));
48
+ }
@@ -0,0 +1,13 @@
1
+ import cors from 'cors';
2
+ import type { RequestHandler } from 'express';
3
+ import type { McpToolDefinition } from './tools/generator.js';
4
+ /** Browser origins are configured separately from storage destinations. Tickets remain required. */
5
+ export declare function createAppUploadCors(origins: string[]): (req: cors.CorsRequest, res: {
6
+ statusCode?: number | undefined;
7
+ setHeader(key: string, value: string): any;
8
+ end(): any;
9
+ }, next: (err?: any) => any) => void;
10
+ /** A ticket grants one bounded PUT to one server-issued storage URL, never arbitrary proxying. */
11
+ export declare function relayUploadTool(tool: McpToolDefinition, origin: string, storageOrigin: string): McpToolDefinition;
12
+ export declare const appUploadHandler: RequestHandler;
13
+ //# sourceMappingURL=app-upload-relay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-upload-relay.d.ts","sourceRoot":"","sources":["../src/app-upload-relay.ts"],"names":[],"mappings":"AAIA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAG9D,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE;;;;qCAOpD;AAcD,kGAAkG;AAClG,wBAAgB,eAAe,CAC7B,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,iBAAiB,CAoCnB;AAED,eAAO,MAAM,gBAAgB,EAAE,cA8E9B,CAAC"}