tunc-mcp 0.0.0-stage → 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 TUNC LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,209 @@
1
- # Temporary Holding Version
1
+ # tunc-mcp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Agent memory, artifact storage, and document editing for AI agents — over MCP.**
4
+
5
+ A small, dependency-free MCP (Model Context Protocol) client for three hosted
6
+ services that AI agents and multi-agent systems actually need:
7
+
8
+ | Service | What it is | MCP endpoint |
9
+ |---|---|---|
10
+ | **Tunc Orb** | **Agent memory database** — durable records, logs and structured state shared by every agent you run | `https://mcp.tuncorb.com/mcp` |
11
+ | **Tunc Art** | **Artifact storage and private file sharing** — agent-generated files behind short private links | `https://mcp.tuncart.com/mcp` |
12
+ | **Tunc Doc** | **Documents, spreadsheets and slide decks** — import/export DOCX, XLSX, PPTX, PDF | `https://mcp.tuncdoc.com/mcp` |
13
+
14
+ All three are also reachable over **A2A** (agent-to-agent) and plain **REST**, so
15
+ the same account works whether your agent speaks MCP, A2A, or HTTP.
16
+
17
+ ## Why this exists
18
+
19
+ Most agent stacks lose state the moment a context window rolls over. Writes from
20
+ two agents at once silently clobber each other. Artifacts end up as files on
21
+ someone's laptop. This gives an agent three boring, reliable primitives instead:
22
+
23
+ - **Memory that survives the conversation.** Records persist across sessions,
24
+ across agents, across models. `data_read` / `data_write` / `data_update` /
25
+ `data_delete`, with revision-guarded writes.
26
+ - **Artifacts with links you can send.** Upload a file, get a short private URL
27
+ back. No bucket configuration.
28
+ - **Documents an agent can actually produce.** Real DOCX, XLSX and PPTX, not
29
+ markdown pretending to be a report.
30
+
31
+ ### Concurrency is the interesting part
32
+
33
+ `data_update` accepts `if_revision`. Two agents writing the same record do not
34
+ race: the second gets a `revision_conflict`, re-reads, and retries. That turns a
35
+ lost-update bug — the classic multi-agent failure where a plausible but wrong
36
+ number survives — into a loud retry. If you run agent swarms that share state,
37
+ use it.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ npm install tunc-mcp
43
+ ```
44
+
45
+ Node 18 or newer. No dependencies. Get an API key at
46
+ <https://tunchub.com/account/keys/new> — you can scope it read-only.
47
+
48
+ ## Options
49
+
50
+ Every helper takes an object. Only the key is required, and it falls back to `TUNC_API_KEY`.
51
+
52
+ ```js
53
+ import { orb, art, doc, connect, SERVERS } from 'tunc-mcp';
54
+
55
+ const memory = orb({
56
+ apiKey: process.env.TUNC_API_KEY,
57
+ endpoint: 'https://mcp.tuncorb.com/mcp', // override: staging, a proxy, or a local mock
58
+ });
59
+ ```
60
+
61
+ - `apiKey` — defaults to `TUNC_API_KEY`. It is checked when the client is constructed, so a missing key fails immediately rather than on the first call.
62
+ - `endpoint` — replaces the built-in URL for that service. This is what you use to point the client at a test server.
63
+ - `service` — `"orb"`, `"art"` or `"doc"`, if you construct `TuncMcpClient` directly instead of using `orb()` / `art()` / `doc()`.
64
+
65
+ `SERVERS` is the map of default endpoints. `connect(key)` returns all three clients at once.
66
+
67
+ ## What comes back
68
+
69
+ `callTool()` returns the server's MCP result unchanged:
70
+
71
+ ```js
72
+ { content: [{ type: "text", text: "<json string>" }], structuredContent: { /* … */ }, isError: false }
73
+ ```
74
+
75
+ Confusingly, the same payload often appears twice — as `structuredContent` and again serialised into `content[0].text`. Use `structuredContent` when it is there. When you only want the text, `callText()` unwraps it for you:
76
+
77
+ ```js
78
+ const text = await memory.callText('data_read', { name: 'contacts/ada' });
79
+ ```
80
+
81
+ Tool names come from the server, not from this package. Call `listTools()` to see what a service actually offers before writing against it — the list is not hard-coded here and changes as the servers change.
82
+
83
+ ## ESM only
84
+
85
+ This package is ESM. In a CommonJS project, either set `"type": "module"` in `package.json` or import it from an `.mjs` file. Otherwise Node fails with `SyntaxError: Cannot use import statement outside a module`.
86
+
87
+ ## Use
88
+
89
+ ```js
90
+ import { orb, art, doc } from 'tunc-mcp';
91
+
92
+ const memory = orb(); // reads TUNC_API_KEY
93
+
94
+ // Agent memory: durable records, revision-guarded
95
+ await memory.callTool('data_write', {
96
+ name: 'contacts/ada',
97
+ about: 'Primary contact, Example Ltd',
98
+ value: { email: 'ada@example.com', timezone: 'Europe/London' },
99
+ });
100
+
101
+ // Artifacts: store a file, get a private link
102
+ const files = art();
103
+ await files.callTool('art_write', {
104
+ title: 'quarterly-report.pdf',
105
+ mime_type: 'application/pdf',
106
+ content_base64: base64Bytes,
107
+ });
108
+
109
+ // Documents: build something a human can open and edit
110
+ const docs = doc();
111
+ await docs.callTool('doc_create', {
112
+ title: 'Q4 summary',
113
+ markdown: '# Q4\n\nRevenue up 12%.',
114
+ });
115
+ ```
116
+
117
+ Discover what any service offers:
118
+
119
+ ```js
120
+ const tools = await orb().listTools();
121
+ console.log(tools.map((t) => t.name).join(', '));
122
+ ```
123
+
124
+ ## CLI
125
+
126
+ ```bash
127
+ export TUNC_API_KEY=tunc_...
128
+
129
+ npx tunc-mcp services
130
+ npx tunc-mcp tools --service orb
131
+ npx tunc-mcp call data_read '{"name":"contacts/ada"}' --service orb
132
+ ```
133
+
134
+ ## Wire it into an MCP client
135
+
136
+ Any MCP-capable host works — Claude Desktop, Cursor, Claude Code, Codex, a custom
137
+ orchestrator. Point it at the endpoint and pass the key as a bearer header:
138
+
139
+ ```json
140
+ {
141
+ "mcpServers": {
142
+ "tunc-orb": {
143
+ "type": "http",
144
+ "url": "https://mcp.tuncorb.com/mcp",
145
+ "headers": { "Authorization": "Bearer ${TUNC_API_KEY}" }
146
+ }
147
+ }
148
+ }
149
+ ```
150
+
151
+ ## Agent-to-agent
152
+
153
+ Every service publishes an A2A agent card, so agents that speak A2A can discover
154
+ and call them without a human in the loop:
155
+
156
+ - <https://tuncorb.com/.well-known/agent-card.json>
157
+ - <https://tuncart.com/.well-known/agent-card.json>
158
+ - <https://tuncdoc.com/.well-known/agent-card.json>
159
+
160
+ ## What this package does not do
161
+
162
+ It is a client. It does not host anything, and it does not bundle an agent
163
+ runtime. If you want the workspace these services belong to — a multiplayer
164
+ chat where people and agents work together — that is a desktop and mobile app:
165
+ <https://tunchub.com>.
166
+
167
+ ## Errors
168
+
169
+ Everything throws `TuncMcpError` with a `status`, a `code` and the server's
170
+ message. A `401` means the key is missing, revoked, or not scoped for that
171
+ service; the message says which.
172
+
173
+ ## 中文
174
+
175
+ **面向 AI 智能体的记忆数据库、制品存储与文档编辑 —— 通过 MCP 接入。**
176
+
177
+ `tunc-mcp` 是一个零依赖的 MCP 客户端,连接三个托管服务,解决多智能体系统里最常见的问题:
178
+
179
+ | 服务 | 用途 | 接入点 |
180
+ |---|---|---|
181
+ | **Tunc Orb** | **智能体记忆数据库** —— 持久保存记录、日志与结构化状态,可在所有智能体之间共享 | `https://mcp.tuncorb.com/mcp` |
182
+ | **Tunc Art** | **制品存储与文件分享** —— 保存智能体生成的文件,返回私密短链接 | `https://mcp.tuncart.com/mcp` |
183
+ | **Tunc Doc** | **文档、表格与幻灯片** —— 可导入导出 DOCX、XLSX、PPTX、PDF | `https://mcp.tuncdoc.com/mcp` |
184
+
185
+ 三个服务同时支持 **MCP**、**A2A**(智能体间通信)与 **REST**,同一个账号即可通用。
186
+
187
+ ### 为什么需要它
188
+
189
+ 多数智能体框架在上下文窗口滚动之后就会丢失状态;两个智能体同时写入会互相覆盖;生成的制品散落在本地磁盘上。这里提供三个朴素可靠的基础能力:
190
+
191
+ - **能跨越对话的记忆。** 记录跨会话、跨智能体、跨模型持久保存,写入支持 `if_revision` 乐观并发控制。
192
+ - **可分享的制品链接。** 上传文件即得到私密短链接,无需配置对象存储。
193
+ - **智能体能够真正产出的文档。** 真实的 DOCX、XLSX 与 PPTX,而不是伪装成报告的 Markdown。
194
+
195
+ ### 并发写入
196
+
197
+ `data_update` 接受 `if_revision`。两个智能体写同一条记录时不会互相覆盖:后到的写入收到 `revision_conflict`,重新读取后重试。这把多智能体最常见的“静默丢更新”故障,变成一个可以被发现的错误。
198
+
199
+ ```bash
200
+ npm install tunc-mcp
201
+ ```
202
+
203
+ API 密钥:<https://tunchub.com/account/keys/new>(可设为只读)。
204
+
205
+ 完整的多人协作工作空间(人与多个智能体共享同一实时对话)见 <https://tunchub.com>。
206
+
207
+ ## License
208
+
209
+ MIT © TUNC LLC
package/bin/cli.js ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ // tunc-mcp — inspect and call the Tunc MCP servers from a terminal.
3
+ //
4
+ // export TUNC_API_KEY=tunc_...
5
+ // npx tunc-mcp tools --service orb
6
+ // npx tunc-mcp call data_read '{"name":"contacts/ada"}'
7
+
8
+ import { SERVERS, TuncMcpClient, TuncMcpError } from '../src/client.js';
9
+
10
+ const USAGE = `tunc-mcp — MCP client for Tunc Orb, Tunc Art and Tunc Doc
11
+
12
+ Usage:
13
+ tunc-mcp services
14
+ tunc-mcp tools [--service orb|art|doc] [--json]
15
+ tunc-mcp call <tool> [json-args] [--service orb|art|doc]
16
+
17
+ Environment:
18
+ TUNC_API_KEY required. Create one at https://tunchub.com/account/keys/new
19
+ `;
20
+
21
+ function parseArgs(argv) {
22
+ const args = { _: [], service: 'orb', json: false };
23
+ for (let i = 0; i < argv.length; i += 1) {
24
+ const arg = argv[i];
25
+ if (arg === '--service') args.service = argv[++i];
26
+ else if (arg === '--json') args.json = true;
27
+ else if (arg === '--help' || arg === '-h') args.help = true;
28
+ else args._.push(arg);
29
+ }
30
+ return args;
31
+ }
32
+
33
+ async function main() {
34
+ const args = parseArgs(process.argv.slice(2));
35
+ const [command, ...rest] = args._;
36
+
37
+ if (args.help || !command || command === 'services') {
38
+ if (command === 'services') {
39
+ console.log(JSON.stringify(SERVERS, null, 2));
40
+ return;
41
+ }
42
+ console.log(USAGE);
43
+ return;
44
+ }
45
+
46
+ const client = new TuncMcpClient({ service: args.service });
47
+
48
+ if (command === 'tools') {
49
+ const tools = await client.listTools();
50
+ if (args.json) {
51
+ console.log(JSON.stringify(tools, null, 2));
52
+ return;
53
+ }
54
+ console.log(`${tools.length} tools on ${args.service} (${client.endpoint})\n`);
55
+ for (const tool of tools) {
56
+ console.log(` ${tool.name}${tool.description ? ` — ${tool.description.split('.')[0]}` : ''}`);
57
+ }
58
+ return;
59
+ }
60
+
61
+ if (command === 'call') {
62
+ const [name, rawArgs] = rest;
63
+ if (!name) {
64
+ console.error('call needs a tool name. Run: tunc-mcp tools');
65
+ process.exitCode = 1;
66
+ return;
67
+ }
68
+ let parsed = {};
69
+ if (rawArgs) {
70
+ try {
71
+ parsed = JSON.parse(rawArgs);
72
+ } catch {
73
+ console.error('That is not valid JSON. Quote it, e.g. \'{"name":"x"}\'');
74
+ process.exitCode = 1;
75
+ return;
76
+ }
77
+ }
78
+ const result = await client.callTool(name, parsed);
79
+ console.log(JSON.stringify(result, null, 2));
80
+ return;
81
+ }
82
+
83
+ console.error(`Unknown command: ${command}\n`);
84
+ console.log(USAGE);
85
+ process.exitCode = 1;
86
+ }
87
+
88
+ main().catch((error) => {
89
+ if (error instanceof TuncMcpError) {
90
+ console.error(`tunc-mcp: ${error.message}`);
91
+ if (error.status) console.error(` HTTP ${error.status}`);
92
+ } else {
93
+ console.error(`tunc-mcp: ${error.message}`);
94
+ }
95
+ process.exitCode = 1;
96
+ });
package/package.json CHANGED
@@ -1,6 +1,58 @@
1
1
  {
2
2
  "name": "tunc-mcp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "MCP client for Tunc Orb (agent memory database), Tunc Art (artifact storage and private file sharing) and Tunc Doc (documents, spreadsheets, decks).",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "agent-memory",
9
+ "agent-database",
10
+ "memory",
11
+ "agent",
12
+ "agents",
13
+ "multi-agent",
14
+ "multi-agent-orchestration",
15
+ "artifact",
16
+ "artifacts",
17
+ "artifact-storage",
18
+ "file-sharing",
19
+ "private-links",
20
+ "storage",
21
+ "database",
22
+ "records",
23
+ "documents",
24
+ "spreadsheets",
25
+ "slide-decks",
26
+ "a2a",
27
+ "agent-to-agent",
28
+ "ai-agents",
29
+ "llm",
30
+ "tunc"
31
+ ],
32
+ "type": "module",
33
+ "main": "./src/index.js",
34
+ "exports": {
35
+ ".": "./src/index.js",
36
+ "./client": "./src/client.js"
37
+ },
38
+ "bin": {
39
+ "tunc-mcp": "./bin/cli.js"
40
+ },
41
+ "files": [
42
+ "src",
43
+ "bin",
44
+ "README.md"
45
+ ],
46
+ "engines": {
47
+ "node": ">=18"
48
+ },
49
+ "scripts": {
50
+ "test": "node --test"
51
+ },
52
+ "license": "MIT",
53
+ "homepage": "https://tuncorb.com",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "https://github.com/TUNC-AI/tunc-mcp.git"
57
+ }
58
+ }
package/src/client.js ADDED
@@ -0,0 +1,182 @@
1
+ // Minimal MCP (Model Context Protocol) client over streamable HTTP.
2
+ //
3
+ // It speaks just enough of the protocol to talk to the Tunc servers: initialize,
4
+ // tools/list and tools/call, with JSON-RPC 2.0 envelopes and event-stream
5
+ // responses. No dependencies; Node 18+ fetch only.
6
+ //
7
+ // Servers:
8
+ // Tunc Orb https://mcp.tuncorb.com/mcp agent memory database
9
+ // Tunc Art https://mcp.tuncart.com/mcp artifact storage, private links
10
+ // Tunc Doc https://mcp.tuncdoc.com/mcp documents, spreadsheets, decks
11
+
12
+ export const SERVERS = Object.freeze({
13
+ orb: 'https://mcp.tuncorb.com/mcp',
14
+ art: 'https://mcp.tuncart.com/mcp',
15
+ doc: 'https://mcp.tuncdoc.com/mcp',
16
+ });
17
+
18
+ export class TuncMcpError extends Error {
19
+ constructor(message, { code, status, body } = {}) {
20
+ super(message);
21
+ this.name = 'TuncMcpError';
22
+ this.code = code;
23
+ this.status = status;
24
+ this.body = body;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Pull the JSON-RPC payload out of an event-stream body, or a plain JSON body.
30
+ * Streamable HTTP lets a server answer either way; Tunc answers JSON, other
31
+ * MCP servers may answer text/event-stream, so both are handled.
32
+ */
33
+ export function parseBody(contentType, text) {
34
+ if (!text) return null;
35
+ if (!/text\/event-stream/i.test(contentType ?? '')) {
36
+ try {
37
+ return JSON.parse(text);
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+
43
+ let last = null;
44
+ for (const block of text.split(/\r?\n\r?\n/)) {
45
+ const data = block
46
+ .split(/\r?\n/)
47
+ .filter((line) => line.startsWith('data:'))
48
+ .map((line) => line.slice(5).trimStart())
49
+ .join('\n');
50
+ if (!data) continue;
51
+ try {
52
+ last = JSON.parse(data);
53
+ } catch {
54
+ // A partial frame: keep the previous complete one.
55
+ }
56
+ }
57
+ return last;
58
+ }
59
+
60
+ export class TuncMcpClient {
61
+ #endpoint;
62
+ #apiKey;
63
+ #sessionId = null;
64
+ #nextId = 1;
65
+ #initialized = false;
66
+
67
+ constructor({ service = 'orb', endpoint, apiKey }) {
68
+ this.#endpoint = endpoint ?? SERVERS[service];
69
+ if (!this.#endpoint) {
70
+ throw new TuncMcpError(`Unknown service "${service}". Use orb, art or doc, or pass an endpoint.`);
71
+ }
72
+ this.#apiKey = apiKey ?? process.env.TUNC_API_KEY;
73
+ if (!this.#apiKey) {
74
+ throw new TuncMcpError(
75
+ 'No API key. Pass apiKey or set TUNC_API_KEY. Create one at https://tunchub.com/account/keys/new',
76
+ );
77
+ }
78
+ }
79
+
80
+ get endpoint() {
81
+ return this.#endpoint;
82
+ }
83
+
84
+ async #post(payload) {
85
+ const headers = {
86
+ 'content-type': 'application/json',
87
+ accept: 'application/json, text/event-stream',
88
+ authorization: `Bearer ${this.#apiKey}`,
89
+ };
90
+ if (this.#sessionId) headers['mcp-session-id'] = this.#sessionId;
91
+
92
+ const response = await fetch(this.#endpoint, {
93
+ method: 'POST',
94
+ headers,
95
+ body: JSON.stringify(payload),
96
+ });
97
+
98
+ const session = response.headers.get('mcp-session-id');
99
+ if (session) this.#sessionId = session;
100
+
101
+ const text = await response.text();
102
+ const body = parseBody(response.headers.get('content-type'), text);
103
+
104
+ if (response.status === 401) {
105
+ // The server knows why it refused: missing key, revoked, or wrong scope.
106
+ // Keep its words and add ours, rather than replacing a specific answer
107
+ // with a generic one.
108
+ const server = body?.error?.message;
109
+ throw new TuncMcpError(
110
+ server
111
+ ? `${server} (the API key is missing, revoked, or not scoped for this service)`
112
+ : 'Unauthorized. The API key is missing, revoked, or not scoped for this service.',
113
+ { status: 401, code: body?.error?.code, body },
114
+ );
115
+ }
116
+
117
+ if (!response.ok) {
118
+ throw new TuncMcpError(body?.error?.message ?? `HTTP ${response.status}`, {
119
+ status: response.status,
120
+ code: body?.error?.code,
121
+ body,
122
+ });
123
+ }
124
+
125
+ if (body?.error) {
126
+ throw new TuncMcpError(body.error.message ?? 'JSON-RPC error', {
127
+ code: body.error.code,
128
+ status: response.status,
129
+ body,
130
+ });
131
+ }
132
+
133
+ return body?.result;
134
+ }
135
+
136
+ async #rpc(method, params) {
137
+ return this.#post({ jsonrpc: '2.0', id: this.#nextId++, method, params });
138
+ }
139
+
140
+ async initialize() {
141
+ if (this.#initialized) return this;
142
+ const result = await this.#rpc('initialize', {
143
+ protocolVersion: '2025-06-18',
144
+ capabilities: {},
145
+ clientInfo: { name: 'tunc-mcp', version: '0.1.0' },
146
+ });
147
+ // Notifications carry no id and expect no body.
148
+ await fetch(this.#endpoint, {
149
+ method: 'POST',
150
+ headers: {
151
+ 'content-type': 'application/json',
152
+ accept: 'application/json, text/event-stream',
153
+ authorization: `Bearer ${this.#apiKey}`,
154
+ ...(this.#sessionId ? { 'mcp-session-id': this.#sessionId } : {}),
155
+ },
156
+ body: JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' }),
157
+ }).catch(() => {});
158
+ this.serverInfo = result?.serverInfo ?? null;
159
+ this.capabilities = result?.capabilities ?? null;
160
+ this.#initialized = true;
161
+ return this;
162
+ }
163
+
164
+ async listTools() {
165
+ await this.initialize();
166
+ const result = await this.#rpc('tools/list', {});
167
+ return result?.tools ?? [];
168
+ }
169
+
170
+ async callTool(name, args = {}) {
171
+ await this.initialize();
172
+ return this.#rpc('tools/call', { name, arguments: args });
173
+ }
174
+
175
+ /** Convenience: the text content of a tool result, joined. */
176
+ async callText(name, args = {}) {
177
+ const result = await this.callTool(name, args);
178
+ const parts = Array.isArray(result?.content) ? result.content : [];
179
+ const text = parts.filter((p) => p?.type === 'text').map((p) => p.text).join('\n');
180
+ return text || result;
181
+ }
182
+ }
package/src/index.js ADDED
@@ -0,0 +1,33 @@
1
+ // Convenience layer over the three Tunc MCP servers.
2
+ //
3
+ // Tunc Orb — agent memory database: durable records and logs for agents and
4
+ // agent swarms, revision-guarded so concurrent writers cannot clobber.
5
+ // Tunc Art — artifact storage and private file sharing: agent-generated files
6
+ // with short private links.
7
+ // Tunc Doc — documents, spreadsheets and slide decks, import/export DOCX,
8
+ // XLSX, PPTX and PDF.
9
+
10
+ import { SERVERS, TuncMcpClient, TuncMcpError, parseBody } from './client.js';
11
+
12
+ export { SERVERS, TuncMcpClient, TuncMcpError, parseBody };
13
+
14
+ export function orb(options = {}) {
15
+ return new TuncMcpClient({ service: 'orb', ...options });
16
+ }
17
+
18
+ export function art(options = {}) {
19
+ return new TuncMcpClient({ service: 'art', ...options });
20
+ }
21
+
22
+ export function doc(options = {}) {
23
+ return new TuncMcpClient({ service: 'doc', ...options });
24
+ }
25
+
26
+ /** All three clients from one key. */
27
+ export function connect(apiKey = process.env.TUNC_API_KEY) {
28
+ return {
29
+ orb: orb({ apiKey }),
30
+ art: art({ apiKey }),
31
+ doc: doc({ apiKey }),
32
+ };
33
+ }