@tinybirdco/devtools-mcp 0.0.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 (38) hide show
  1. package/README.md +330 -0
  2. package/dist/config.d.ts +66 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +260 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/index.d.ts +9 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +20 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/server.d.ts +14 -0
  11. package/dist/server.d.ts.map +1 -0
  12. package/dist/server.js +37 -0
  13. package/dist/server.js.map +1 -0
  14. package/dist/tools/execute-query.d.ts +11 -0
  15. package/dist/tools/execute-query.d.ts.map +1 -0
  16. package/dist/tools/execute-query.js +38 -0
  17. package/dist/tools/execute-query.js.map +1 -0
  18. package/dist/tools/get-resource.d.ts +11 -0
  19. package/dist/tools/get-resource.d.ts.map +1 -0
  20. package/dist/tools/get-resource.js +67 -0
  21. package/dist/tools/get-resource.js.map +1 -0
  22. package/dist/tools/list-branches.d.ts +11 -0
  23. package/dist/tools/list-branches.d.ts.map +1 -0
  24. package/dist/tools/list-branches.js +41 -0
  25. package/dist/tools/list-branches.js.map +1 -0
  26. package/dist/tools/list-kafka-topics.d.ts +11 -0
  27. package/dist/tools/list-kafka-topics.d.ts.map +1 -0
  28. package/dist/tools/list-kafka-topics.js +46 -0
  29. package/dist/tools/list-kafka-topics.js.map +1 -0
  30. package/dist/tools/list-resources.d.ts +11 -0
  31. package/dist/tools/list-resources.d.ts.map +1 -0
  32. package/dist/tools/list-resources.js +99 -0
  33. package/dist/tools/list-resources.js.map +1 -0
  34. package/dist/tools/preview-kafka-topic.d.ts +11 -0
  35. package/dist/tools/preview-kafka-topic.d.ts.map +1 -0
  36. package/dist/tools/preview-kafka-topic.js +93 -0
  37. package/dist/tools/preview-kafka-topic.js.map +1 -0
  38. package/package.json +38 -0
package/README.md ADDED
@@ -0,0 +1,330 @@
1
+ # Tinybird DevTools MCP
2
+
3
+ > **Note:** This package is experimental. APIs may change between versions.
4
+
5
+ `@tinybirdco/devtools-mcp` is a Model Context Protocol (MCP) server that provides Tinybird development tools and utilities for coding agents like Claude, Cursor, and Codex.
6
+
7
+ ## Getting Started
8
+
9
+ ### Requirements
10
+
11
+ - [Node.js](https://nodejs.org/) v20.0.0 or newer
12
+ - A Tinybird API token
13
+
14
+ Add the following config to your MCP client:
15
+
16
+ ```json
17
+ {
18
+ "mcpServers": {
19
+ "tinybird": {
20
+ "command": "npx",
21
+ "args": ["-y", "@tinybirdco/devtools-mcp@latest"],
22
+ "env": {
23
+ "TINYBIRD_TOKEN": "p.your-token-here"
24
+ }
25
+ }
26
+ }
27
+ }
28
+ ```
29
+
30
+ | Environment Variable | Description | Default |
31
+ |---------------------|-------------|---------|
32
+ | `TINYBIRD_TOKEN` | Tinybird API token | Required |
33
+ | `TINYBIRD_URL` | Tinybird API base URL | `https://api.tinybird.co` |
34
+
35
+ > [!TIP]
36
+ > For US region, set `TINYBIRD_URL` to `https://api.us-east.tinybird.co`.
37
+
38
+ ### MCP Client Configuration
39
+
40
+ <details>
41
+ <summary>Claude Code</summary>
42
+
43
+ Use the Claude Code CLI to add the Tinybird DevTools MCP server:
44
+
45
+ ```bash
46
+ claude mcp add tinybird -e TINYBIRD_TOKEN=p.your-token-here -- npx -y @tinybirdco/devtools-mcp@latest
47
+ ```
48
+
49
+ </details>
50
+
51
+ <details>
52
+ <summary>Claude Desktop</summary>
53
+
54
+ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "tinybird": {
60
+ "command": "npx",
61
+ "args": ["-y", "@tinybirdco/devtools-mcp@latest"],
62
+ "env": {
63
+ "TINYBIRD_TOKEN": "p.your-token-here"
64
+ }
65
+ }
66
+ }
67
+ }
68
+ ```
69
+
70
+ </details>
71
+
72
+ <details>
73
+ <summary>Cursor</summary>
74
+
75
+ Go to `Cursor Settings` → `MCP` → `New MCP Server`. Use the config provided above.
76
+
77
+ </details>
78
+
79
+ <details>
80
+ <summary>Codex</summary>
81
+
82
+ ```bash
83
+ codex mcp add tinybird -e TINYBIRD_TOKEN=p.your-token-here -- npx -y @tinybirdco/devtools-mcp@latest
84
+ ```
85
+
86
+ </details>
87
+
88
+ <details>
89
+ <summary>VS Code / Copilot</summary>
90
+
91
+ ```bash
92
+ code --add-mcp '{"name":"tinybird","command":"npx","args":["-y","@tinybirdco/devtools-mcp@latest"],"env":{"TINYBIRD_TOKEN":"p.your-token-here"}}'
93
+ ```
94
+
95
+ </details>
96
+
97
+ ## Quick Start
98
+
99
+ Once configured, your coding agent can interact with your Tinybird workspace:
100
+
101
+ ```
102
+ Tinybird, show me all resources in my workspace
103
+ ```
104
+
105
+ ```
106
+ Tinybird, run a SQL query to count rows in my events table
107
+ ```
108
+
109
+ ```
110
+ Tinybird, list all my Kafka connections
111
+ ```
112
+
113
+ ```
114
+ Tinybird, preview data from my Kafka topic
115
+ ```
116
+
117
+ ## MCP Tools
118
+
119
+ <details>
120
+ <summary><code>execute_query</code></summary>
121
+
122
+ Execute SQL queries against your Tinybird workspace.
123
+
124
+ **When to use:**
125
+ - Query datasources and explore data
126
+ - Test SQL queries before creating pipes
127
+ - Debug data issues
128
+ - Verify data ingestion
129
+
130
+ **Input:**
131
+ - `query` (required) - The SQL query to execute
132
+
133
+ **Output:**
134
+ - Query results in JSON format
135
+
136
+ **Example prompts:**
137
+ - "Tinybird, count the rows in my events table"
138
+ - "Tinybird, show me the schema of the users datasource"
139
+ - "Tinybird, what's the average response time from my api_logs?"
140
+
141
+ </details>
142
+
143
+ <details>
144
+ <summary><code>list_resources</code></summary>
145
+
146
+ List all resources in your Tinybird workspace.
147
+
148
+ **When to use:**
149
+ - Explore workspace structure
150
+ - Get an overview of datasources, pipes, and connections
151
+ - Find resource names before fetching full definitions
152
+
153
+ **Input:**
154
+ - `type` (optional) - Filter by resource type: `'datasource'`, `'pipe'`, or `'connection'`
155
+ - `environment` (optional) - Environment to query: `'cloud'` (default), `'local'`, or a branch name
156
+
157
+ **Output:**
158
+ - JSON array with each resource's id, name, type, and description
159
+
160
+ **Example prompts:**
161
+ - "Tinybird, show me all resources in my workspace"
162
+ - "Tinybird, list all my datasources"
163
+ - "Tinybird, what pipes do I have?"
164
+ - "Tinybird, list resources in my feature_branch"
165
+ - "Tinybird, show me datasources in local"
166
+
167
+ </details>
168
+
169
+ <details>
170
+ <summary><code>get_resource</code></summary>
171
+
172
+ Get the full datafile content of a specific resource.
173
+
174
+ **When to use:**
175
+ - View the complete definition of a datasource, pipe, or connection
176
+ - Understand resource schemas and configurations
177
+ - Review SQL transformations in pipes
178
+
179
+ **Input:**
180
+ - `name` (required) - The name of the resource to fetch
181
+ - `type` (required) - The resource type: `'datasource'`, `'pipe'`, or `'connection'`
182
+ - `environment` (optional) - Environment to query: `'cloud'` (default), `'local'`, or a branch name
183
+
184
+ **Output:**
185
+ - Raw datafile content as text
186
+
187
+ **Example prompts:**
188
+ - "Tinybird, show me the definition of my events datasource"
189
+ - "Tinybird, get the full content of the analytics_api pipe"
190
+ - "Tinybird, what's the schema of my users datasource?"
191
+ - "Tinybird, get the events datasource from my feature_branch"
192
+
193
+ </details>
194
+
195
+ <details>
196
+ <summary><code>list_branches</code></summary>
197
+
198
+ List all branches (environments) in your Tinybird workspace.
199
+
200
+ **When to use:**
201
+ - See available branches before querying resources from a specific branch
202
+ - Check which development branches exist
203
+ - Find branch names to use with the `environment` parameter
204
+
205
+ **Input:**
206
+ - None
207
+
208
+ **Output:**
209
+ - JSON array with each branch's id, name, and created_at timestamp
210
+
211
+ **Example prompts:**
212
+ - "Tinybird, list all my branches"
213
+ - "Tinybird, what branches do I have?"
214
+ - "Tinybird, show me available environments"
215
+
216
+ </details>
217
+
218
+ <details>
219
+ <summary><code>list_kafka_topics</code></summary>
220
+
221
+ List available Kafka topics for a connection.
222
+
223
+ **When to use:**
224
+ - Discover available topics before creating streaming datasources
225
+ - Verify Kafka connection is working
226
+
227
+ **Input:**
228
+ - `connection_id` (required) - The ID of the Kafka connection (get from `list_resources` with type `connection`)
229
+
230
+ **Output:**
231
+ - JSON array of available Kafka topics
232
+
233
+ **Example prompts:**
234
+ - "Tinybird, what Kafka topics are available on my connection?"
235
+
236
+ </details>
237
+
238
+ <details>
239
+ <summary><code>preview_kafka_topic</code></summary>
240
+
241
+ Preview data from a Kafka topic to understand its schema and content.
242
+
243
+ **When to use:**
244
+ - Explore message structure before creating datasources
245
+ - Verify data is flowing through Kafka
246
+ - Debug ingestion issues
247
+
248
+ **Input:**
249
+ - `connection_id` (required) - The ID of the Kafka connection
250
+ - `topic` (required) - The Kafka topic name to preview
251
+ - `group_id` (optional) - Kafka consumer group ID
252
+
253
+ **Output:**
254
+ - JSON with topic schema, sample messages, and metadata
255
+
256
+ **Example prompts:**
257
+ - "Tinybird, preview data from the events topic"
258
+ - "Tinybird, show me the schema of my Kafka messages"
259
+
260
+ </details>
261
+
262
+ ## Configuration
263
+
264
+ The server resolves configuration in the following priority order:
265
+
266
+ ### 1. Environment Variables (Recommended)
267
+
268
+ Set `TINYBIRD_TOKEN` and optionally `TINYBIRD_URL`:
269
+
270
+ ```json
271
+ {
272
+ "env": {
273
+ "TINYBIRD_TOKEN": "p.your-token-here",
274
+ "TINYBIRD_URL": "https://api.us-east.tinybird.co"
275
+ }
276
+ }
277
+ ```
278
+
279
+ ### 2. Config Files (Fallback)
280
+
281
+ If environment variables are not set, the server looks for config files:
282
+
283
+ **`tinybird.json`** (created by `npx @tinybirdco/sdk init`):
284
+
285
+ ```json
286
+ {
287
+ "token": "${TINYBIRD_TOKEN}",
288
+ "baseUrl": "https://api.tinybird.co"
289
+ }
290
+ ```
291
+
292
+ **`.tinyb`** (created by `tb login`):
293
+
294
+ ```json
295
+ {
296
+ "host": "https://api.tinybird.co",
297
+ "token": "p.eyJ..."
298
+ }
299
+ ```
300
+
301
+ Environment variables in `${VAR}` format are automatically resolved from your environment or `.env` files.
302
+
303
+ ## Local Development
304
+
305
+ To run the MCP server locally for development:
306
+
307
+ 1. Clone the repository
308
+ 2. Install dependencies:
309
+ ```bash
310
+ pnpm install
311
+ pnpm build
312
+ ```
313
+ 3. Configure your MCP client to use the local version:
314
+ ```json
315
+ {
316
+ "mcpServers": {
317
+ "tinybird": {
318
+ "command": "node",
319
+ "args": ["/absolute/path/to/mcp/dist/index.js"],
320
+ "env": {
321
+ "TINYBIRD_TOKEN": "p.your-token-here"
322
+ }
323
+ }
324
+ }
325
+ }
326
+ ```
327
+
328
+ ## License
329
+
330
+ MIT
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Configuration loader for tinybird.json and .tinyb files
3
+ * Minimal version for MCP server - only needs token and baseUrl
4
+ */
5
+ /**
6
+ * Tinybird configuration file structure (tinybird.json)
7
+ */
8
+ export interface TinybirdJsonConfig {
9
+ /** API token (supports ${ENV_VAR} interpolation) */
10
+ token: string;
11
+ /** Tinybird API base URL (optional, defaults to EU region) */
12
+ baseUrl?: string;
13
+ }
14
+ /**
15
+ * .tinyb file structure (created by tb login)
16
+ */
17
+ export interface TinybConfig {
18
+ /** Tinybird API host URL */
19
+ host?: string;
20
+ /** Authentication token */
21
+ token?: string;
22
+ /** Map of hosts to tokens */
23
+ tokens?: Record<string, string>;
24
+ }
25
+ /**
26
+ * Resolved configuration with all values expanded
27
+ */
28
+ export interface ResolvedConfig {
29
+ /** Resolved API token */
30
+ token: string;
31
+ /** Tinybird API base URL */
32
+ baseUrl: string;
33
+ }
34
+ /**
35
+ * Environment type for selecting which Tinybird instance to use
36
+ * - "cloud": Main workspace (default)
37
+ * - "local": Local container at localhost:7181
38
+ * - string: Branch name - fetches branch token from API
39
+ */
40
+ export type Environment = "cloud" | "local" | string;
41
+ /**
42
+ * Find a config file by walking up the directory tree
43
+ * Checks for tinybird.json first, then .tinyb
44
+ */
45
+ export declare function findConfigFile(startDir: string): {
46
+ path: string;
47
+ type: "tinybird.json" | ".tinyb";
48
+ } | null;
49
+ /**
50
+ * Load and resolve the configuration
51
+ *
52
+ * Priority order:
53
+ * 1. Environment variables (TINYBIRD_TOKEN, TINYBIRD_URL)
54
+ * 2. tinybird.json file
55
+ * 3. .tinyb file
56
+ */
57
+ export declare function loadConfig(cwd?: string): ResolvedConfig;
58
+ /**
59
+ * Resolve configuration for a specific environment
60
+ *
61
+ * @param baseConfig - Base configuration from tinybird.json or .tinyb
62
+ * @param environment - Environment to use: "cloud" (default), "local", or branch name
63
+ * @returns Resolved configuration with appropriate token and baseUrl
64
+ */
65
+ export declare function resolveEnvironmentConfig(baseConfig: ResolvedConfig, environment?: Environment): Promise<ResolvedConfig>;
66
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AA+BrD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,eAAe,GAAG,QAAQ,CAAA;CAAE,GAAG,IAAI,CAkB1G;AA4FD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,cAAc,CA0BtE;AAqGD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,cAAc,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,cAAc,CAAC,CAqBzB"}
package/dist/config.js ADDED
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Configuration loader for tinybird.json and .tinyb files
3
+ * Minimal version for MCP server - only needs token and baseUrl
4
+ */
5
+ import * as fs from "fs";
6
+ import * as path from "path";
7
+ /**
8
+ * Default base URL (EU region)
9
+ */
10
+ const DEFAULT_BASE_URL = "https://api.tinybird.co";
11
+ /**
12
+ * Local container base URL
13
+ */
14
+ const LOCAL_BASE_URL = "http://localhost:7181";
15
+ /**
16
+ * Config file names in order of priority
17
+ */
18
+ const CONFIG_FILES = ["tinybird.json", ".tinyb"];
19
+ /**
20
+ * Interpolate environment variables in a string
21
+ * Supports ${VAR_NAME} syntax
22
+ */
23
+ function interpolateEnvVars(value) {
24
+ return value.replace(/\$\{([^}]+)\}/g, (_, envVar) => {
25
+ const envValue = process.env[envVar];
26
+ if (envValue === undefined) {
27
+ throw new Error(`Environment variable ${envVar} is not set`);
28
+ }
29
+ return envValue;
30
+ });
31
+ }
32
+ /**
33
+ * Find a config file by walking up the directory tree
34
+ * Checks for tinybird.json first, then .tinyb
35
+ */
36
+ export function findConfigFile(startDir) {
37
+ let currentDir = startDir;
38
+ while (true) {
39
+ // Check each config file type in priority order
40
+ for (const configFile of CONFIG_FILES) {
41
+ const configPath = path.join(currentDir, configFile);
42
+ if (fs.existsSync(configPath)) {
43
+ return { path: configPath, type: configFile };
44
+ }
45
+ }
46
+ const parentDir = path.dirname(currentDir);
47
+ if (parentDir === currentDir) {
48
+ return null;
49
+ }
50
+ currentDir = parentDir;
51
+ }
52
+ }
53
+ /**
54
+ * Load config from tinybird.json format
55
+ */
56
+ function loadTinybirdJsonConfig(configPath) {
57
+ let rawContent;
58
+ try {
59
+ rawContent = fs.readFileSync(configPath, "utf-8");
60
+ }
61
+ catch (error) {
62
+ throw new Error(`Failed to read ${configPath}: ${error.message}`);
63
+ }
64
+ let config;
65
+ try {
66
+ config = JSON.parse(rawContent);
67
+ }
68
+ catch (error) {
69
+ throw new Error(`Failed to parse ${configPath}: ${error.message}`);
70
+ }
71
+ if (!config.token) {
72
+ throw new Error(`Missing 'token' field in ${configPath}`);
73
+ }
74
+ // Resolve token
75
+ let resolvedToken;
76
+ try {
77
+ resolvedToken = interpolateEnvVars(config.token);
78
+ }
79
+ catch (error) {
80
+ throw new Error(`Failed to resolve token in ${configPath}: ${error.message}`);
81
+ }
82
+ // Resolve base URL
83
+ let resolvedBaseUrl = DEFAULT_BASE_URL;
84
+ if (config.baseUrl) {
85
+ try {
86
+ resolvedBaseUrl = interpolateEnvVars(config.baseUrl);
87
+ }
88
+ catch (error) {
89
+ throw new Error(`Failed to resolve baseUrl in ${configPath}: ${error.message}`);
90
+ }
91
+ }
92
+ return {
93
+ token: resolvedToken,
94
+ baseUrl: resolvedBaseUrl,
95
+ };
96
+ }
97
+ /**
98
+ * Load config from .tinyb format (created by tb login)
99
+ */
100
+ function loadTinybConfigFile(configPath) {
101
+ let rawContent;
102
+ try {
103
+ rawContent = fs.readFileSync(configPath, "utf-8");
104
+ }
105
+ catch (error) {
106
+ throw new Error(`Failed to read ${configPath}: ${error.message}`);
107
+ }
108
+ let config;
109
+ try {
110
+ config = JSON.parse(rawContent);
111
+ }
112
+ catch (error) {
113
+ throw new Error(`Failed to parse ${configPath}: ${error.message}`);
114
+ }
115
+ // Get token - prefer direct token, fallback to tokens map with host
116
+ let token = config.token;
117
+ if (!token && config.tokens && config.host) {
118
+ token = config.tokens[config.host];
119
+ }
120
+ if (!token) {
121
+ throw new Error(`Missing 'token' field in ${configPath}. Run 'tb login' to authenticate.`);
122
+ }
123
+ // Get base URL from host field
124
+ let baseUrl = DEFAULT_BASE_URL;
125
+ if (config.host) {
126
+ baseUrl = config.host;
127
+ }
128
+ return {
129
+ token,
130
+ baseUrl,
131
+ };
132
+ }
133
+ /**
134
+ * Load and resolve the configuration
135
+ *
136
+ * Priority order:
137
+ * 1. Environment variables (TINYBIRD_TOKEN, TINYBIRD_URL)
138
+ * 2. tinybird.json file
139
+ * 3. .tinyb file
140
+ */
141
+ export function loadConfig(cwd = process.cwd()) {
142
+ // First, check for direct environment variables
143
+ const envToken = process.env.TINYBIRD_TOKEN;
144
+ if (envToken) {
145
+ const envBaseUrl = process.env.TINYBIRD_URL || DEFAULT_BASE_URL;
146
+ return {
147
+ token: envToken,
148
+ baseUrl: envBaseUrl,
149
+ };
150
+ }
151
+ // Fall back to config file lookup
152
+ const configResult = findConfigFile(cwd);
153
+ if (!configResult) {
154
+ throw new Error(`TINYBIRD_TOKEN environment variable not set and could not find tinybird.json or .tinyb. ` +
155
+ `Either set TINYBIRD_TOKEN or run 'npx @tinybirdco/sdk init' / 'tb login' to create a config file.`);
156
+ }
157
+ if (configResult.type === "tinybird.json") {
158
+ return loadTinybirdJsonConfig(configResult.path);
159
+ }
160
+ else {
161
+ return loadTinybConfigFile(configResult.path);
162
+ }
163
+ }
164
+ /**
165
+ * Get the local workspace name based on current directory
166
+ */
167
+ function getLocalWorkspaceName() {
168
+ const cwd = process.cwd();
169
+ const dirName = path.basename(cwd);
170
+ // Sanitize: replace non-alphanumeric with underscore
171
+ return dirName.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
172
+ }
173
+ /**
174
+ * Get or create local workspace and return its token
175
+ */
176
+ async function getLocalWorkspaceToken() {
177
+ const workspaceName = getLocalWorkspaceName();
178
+ const url = `${LOCAL_BASE_URL}/v0/workspaces`;
179
+ // First, try to get existing workspace
180
+ const listResponse = await fetch(url, {
181
+ method: "GET",
182
+ });
183
+ if (listResponse.ok) {
184
+ const data = (await listResponse.json());
185
+ const existing = data.workspaces?.find((w) => w.name === workspaceName);
186
+ if (existing?.token) {
187
+ return existing.token;
188
+ }
189
+ }
190
+ // Create new workspace
191
+ const createResponse = await fetch(url, {
192
+ method: "POST",
193
+ headers: {
194
+ "Content-Type": "application/json",
195
+ },
196
+ body: JSON.stringify({ name: workspaceName }),
197
+ });
198
+ if (!createResponse.ok) {
199
+ const errorText = await createResponse.text();
200
+ throw new Error(`Failed to create local workspace: ${createResponse.status} ${errorText}`);
201
+ }
202
+ const workspace = (await createResponse.json());
203
+ if (!workspace.token) {
204
+ throw new Error("Local workspace created but no token returned");
205
+ }
206
+ return workspace.token;
207
+ }
208
+ /**
209
+ * Get branch token from Tinybird API
210
+ */
211
+ async function getBranchToken(config, branchName) {
212
+ const url = new URL(`/v0/environments/${encodeURIComponent(branchName)}`, config.baseUrl);
213
+ url.searchParams.set("with_token", "true");
214
+ const response = await fetch(url.toString(), {
215
+ method: "GET",
216
+ headers: {
217
+ Authorization: `Bearer ${config.token}`,
218
+ },
219
+ });
220
+ if (!response.ok) {
221
+ const errorText = await response.text();
222
+ if (response.status === 404) {
223
+ throw new Error(`Branch '${branchName}' not found. Create it first with 'npx @tinybirdco/sdk dev'.`);
224
+ }
225
+ throw new Error(`Failed to get branch '${branchName}': ${response.status} ${errorText}`);
226
+ }
227
+ const branch = (await response.json());
228
+ if (!branch.token) {
229
+ throw new Error(`Branch '${branchName}' exists but no token returned`);
230
+ }
231
+ return branch.token;
232
+ }
233
+ /**
234
+ * Resolve configuration for a specific environment
235
+ *
236
+ * @param baseConfig - Base configuration from tinybird.json or .tinyb
237
+ * @param environment - Environment to use: "cloud" (default), "local", or branch name
238
+ * @returns Resolved configuration with appropriate token and baseUrl
239
+ */
240
+ export async function resolveEnvironmentConfig(baseConfig, environment) {
241
+ // Default to cloud
242
+ if (!environment || environment === "cloud") {
243
+ return baseConfig;
244
+ }
245
+ // Local container
246
+ if (environment === "local") {
247
+ const token = await getLocalWorkspaceToken();
248
+ return {
249
+ token,
250
+ baseUrl: LOCAL_BASE_URL,
251
+ };
252
+ }
253
+ // Branch name - fetch token from API
254
+ const branchToken = await getBranchToken(baseConfig, environment);
255
+ return {
256
+ token: branchToken,
257
+ baseUrl: baseConfig.baseUrl,
258
+ };
259
+ }
260
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Tinybird DevTools MCP Server Entry Point
4
+ *
5
+ * Runs using stdio transport for MCP communication.
6
+ * Load .env files before starting the server.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}