tracecat-mcp-community 1.0.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.
package/.env.example ADDED
@@ -0,0 +1,7 @@
1
+ ## Tracecat MCP Server - Credentials
2
+ ## Copy this file to .env and fill in your values.
3
+ ## DO NOT commit .env to version control.
4
+ TRACECAT_API_URL=http://localhost/api
5
+ TRACECAT_USERNAME=your-email@example.com
6
+ TRACECAT_PASSWORD=your-password-here
7
+ TRACECAT_WORKSPACE_ID=
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 adrojis
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 ADDED
@@ -0,0 +1,267 @@
1
+ <p align="center">
2
+ <img src="assets/banner.png" alt="Tracecat MCP Banner" width="100%">
3
+ </p>
4
+
5
+ # tracecat-mcp-community
6
+
7
+ **A Model Context Protocol (MCP) server for the [Tracecat](https://tracecat.com) SOAR platform — 49 tools across 12 domains.**
8
+
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
+ [![npm version](https://img.shields.io/npm/v/tracecat-mcp-community.svg)](https://www.npmjs.com/package/tracecat-mcp-community)
11
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org)
12
+ [![CI](https://github.com/adrojis/tracecat-mcp-community/actions/workflows/ci.yml/badge.svg)](https://github.com/adrojis/tracecat-mcp-community/actions/workflows/ci.yml)
13
+ [![Tracecat](https://img.shields.io/badge/Tracecat-v1.0.0--beta.31-purple.svg)](https://github.com/TracecatHQ/tracecat)
14
+ [![MCP](https://img.shields.io/badge/MCP-Server-green.svg)](https://modelcontextprotocol.io)
15
+ [![Docker](https://img.shields.io/badge/Docker-ready-blue.svg)](#docker)
16
+
17
+ ---
18
+
19
+ ## What is this?
20
+
21
+ An [MCP server](https://modelcontextprotocol.io) that gives AI assistants (Claude Code, Claude Desktop, etc.) full control over a [Tracecat](https://github.com/TracecatHQ/tracecat) instance through natural language. Manage workflows, actions, cases, secrets, tables, schedules, and more — without leaving your editor.
22
+
23
+ - **49 tools** covering the full Tracecat API surface
24
+ - **Lazy authentication** — MCP transport starts instantly, login happens on first tool call
25
+ - **Auto workspace detection** — no manual workspace ID needed
26
+ - **Session cookie auth** — handles Tracecat's cookie-based auth transparently
27
+
28
+ ---
29
+
30
+ ## Tools
31
+
32
+ | Domain | Tools | Description |
33
+ |---|---|---|
34
+ | **Workflows** | 9 | List, create, get, update, deploy, export, delete, validate, autofix |
35
+ | **Actions** | 5 | List, create, get, update, delete workflow actions |
36
+ | **Executions** | 5 | Run workflows, list/get/cancel executions, compact view |
37
+ | **Cases** | 7 | List, create, get, update, delete cases; add/list comments |
38
+ | **Secrets** | 5 | Search, create, get, update, delete secrets |
39
+ | **Tables** | 5 | List, create, get, update, delete tables |
40
+ | **Columns** | 2 | Create, delete table columns |
41
+ | **Rows** | 6 | List, get, insert, update, delete, batch insert rows |
42
+ | **Schedules** | 5 | List, create, get, update, delete schedules |
43
+ | **Graph** | 3 | Add edges, move nodes, update trigger position |
44
+ | **Webhooks** | 1 | Generate/rotate webhook API keys |
45
+ | **Docs** | 2 | Search Tracecat docs, list available tool documentation |
46
+ | **Templates** | 2 | List and get community workflow templates |
47
+ | **System** | 1 | Health check |
48
+
49
+ > **Total: 49 tools** for complete Tracecat automation.
50
+
51
+ ---
52
+
53
+ ## Quick Start
54
+
55
+ ### Option A: npx (fastest)
56
+
57
+ ```bash
58
+ # Install globally
59
+ npm install -g tracecat-mcp-community
60
+ ```
61
+
62
+ Create a `.env` file wherever you run from (or in the package directory):
63
+
64
+ ```env
65
+ TRACECAT_API_URL=http://localhost/api
66
+ TRACECAT_USERNAME=your-email@example.com
67
+ TRACECAT_PASSWORD=your-password-here
68
+ TRACECAT_WORKSPACE_ID= # Optional — auto-detected if omitted
69
+ ```
70
+
71
+ Add to your `.mcp.json`:
72
+
73
+ ```json
74
+ {
75
+ "mcpServers": {
76
+ "tracecat": {
77
+ "command": "npx",
78
+ "args": ["-y", "tracecat-mcp-community"]
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ ### Option B: From source
85
+
86
+ ```bash
87
+ git clone https://github.com/adrojis/tracecat-mcp-community.git
88
+ cd tracecat-mcp-community
89
+ npm install
90
+ cp .env.example .env # Edit with your credentials
91
+ npm run build
92
+ ```
93
+
94
+ Add to your `.mcp.json`:
95
+
96
+ ```json
97
+ {
98
+ "mcpServers": {
99
+ "tracecat": {
100
+ "command": "node",
101
+ "args": ["/absolute/path/to/tracecat-mcp-community/dist/index.js"]
102
+ }
103
+ }
104
+ }
105
+ ```
106
+
107
+ ### Option C: Docker
108
+
109
+ ```bash
110
+ git clone https://github.com/adrojis/tracecat-mcp-community.git
111
+ cd tracecat-mcp-community
112
+ docker build -t tracecat-mcp-community .
113
+ ```
114
+
115
+ ```json
116
+ {
117
+ "mcpServers": {
118
+ "tracecat": {
119
+ "command": "docker",
120
+ "args": ["run", "-i", "--rm", "--env-file", "/path/to/.env", "tracecat-mcp-community"]
121
+ }
122
+ }
123
+ }
124
+ ```
125
+
126
+ > **Security:** `.env` is gitignored and never committed. Never hardcode credentials in source files. See [SECURITY.md](SECURITY.md).
127
+
128
+ Then restart Claude Code and verify with `/mcp` — you should see the `tracecat` server with 49 tools.
129
+
130
+ ---
131
+
132
+ ## Configuration
133
+
134
+ | Variable | Required | Default | Description |
135
+ |---|---|---|---|
136
+ | `TRACECAT_API_URL` | No | `http://localhost/api` | Tracecat API base URL |
137
+ | `TRACECAT_USERNAME` | **Yes** | — | Login email |
138
+ | `TRACECAT_PASSWORD` | **Yes** | — | Login password |
139
+ | `TRACECAT_WORKSPACE_ID` | No | Auto-detected | Workspace ID (uses first workspace if omitted) |
140
+
141
+ Credentials are loaded from `.env` via [dotenv](https://github.com/motdotla/dotenv). The `.env` file must be in the project root (next to `package.json`).
142
+
143
+ ---
144
+
145
+ ## Architecture
146
+
147
+ ```
148
+ src/
149
+ ├── index.ts # Entry point — StdioTransport + env loading
150
+ ├── server.ts # McpServer creation + tool registration
151
+ ├── client.ts # HTTP client with lazy auth + auto workspace injection
152
+ ├── types.ts # TypeScript interfaces
153
+ └── tools/
154
+ ├── workflows.ts # Workflow CRUD + deploy/export/validate/autofix
155
+ ├── actions.ts # Action CRUD with YAML inputs
156
+ ├── cases.ts # Case management + comments
157
+ ├── executions.ts # Run, list, cancel, inspect executions
158
+ ├── secrets.ts # Secret management
159
+ ├── tables.ts # Tables, columns, and rows
160
+ ├── graph.ts # Graph operations (edges, node positions)
161
+ ├── webhooks.ts # Webhook key rotation
162
+ ├── schedules.ts # Cron/interval scheduling
163
+ ├── docs.ts # Documentation search
164
+ ├── templates.ts # Community workflow templates
165
+ └── system.ts # Health check
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Key Design Decisions
171
+
172
+ | Decision | Rationale |
173
+ |---|---|
174
+ | **Lazy initialization** | MCP transport starts immediately; login happens on first tool call. Avoids blocking Claude Code startup. |
175
+ | **Session cookies** | Tracecat currently uses `fastapiusersauth` cookies, not API keys. The client handles login and cookie extraction automatically. See note below on upcoming API token support. |
176
+ | **YAML string inputs** | Action `inputs` are sent as YAML strings per the Tracecat API contract, not JSON objects. |
177
+ | **POST for updates** | Actions, secrets, and schedules use `POST` for updates instead of the conventional `PATCH`. |
178
+ | **Auto workspace injection** | `workspace_id` is auto-detected and injected as a query parameter on every request. |
179
+ | **Optimistic locking** | Graph operations read `base_version` before patching to prevent concurrent edit conflicts. |
180
+
181
+ ---
182
+
183
+ ## Authentication Roadmap
184
+
185
+ This server currently authenticates via **username/password** (session cookies). The Tracecat team is actively working on **API token authentication**, which will provide a simpler and more secure connection method — no more password in `.env`.
186
+
187
+ We will add API token support as soon as it becomes available upstream. The username/password method will remain supported for backward compatibility.
188
+
189
+ ---
190
+
191
+ ## API Quirks
192
+
193
+ These behaviors differ from typical REST conventions and are handled transparently by the server:
194
+
195
+ | Quirk | Details |
196
+ |---|---|
197
+ | `workspace_id` as query param | Must be `?workspace_id=...`, not a header |
198
+ | POST for updates | `/actions/{id}`, `/secrets/{id}`, `/schedules/{id}` use POST |
199
+ | Actions list endpoint | `GET /actions?workflow_id=...` (not nested under `/workflows`) |
200
+ | Action inputs format | YAML string, not JSON object |
201
+ | Workflow list pagination | Returns `{ items: [...], next_cursor }`, not a plain array |
202
+
203
+ ---
204
+
205
+ ## Development
206
+
207
+ ```bash
208
+ # Watch mode (auto-reload)
209
+ npm run dev
210
+
211
+ # Build TypeScript
212
+ npm run build
213
+
214
+ # Run directly
215
+ node dist/index.js
216
+ ```
217
+
218
+ ## Testing
219
+
220
+ ```bash
221
+ npm run build
222
+ npm test
223
+ ```
224
+
225
+ Tests use Node.js built-in test runner (no extra dependencies). See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
226
+
227
+ ## MCP Inspector
228
+
229
+ The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is a visual debugging tool that lets you browse and test all 49 tools interactively in your browser — useful for verifying your setup, exploring tool schemas, and testing API calls without Claude.
230
+
231
+ From the project root:
232
+
233
+ ```bash
234
+ npx @modelcontextprotocol/inspector node dist/index.js
235
+ ```
236
+
237
+ This starts a local web UI (default: `http://localhost:6274`). Click the **Tools** tab to see all available tools, inspect their input schemas, and execute them against your Tracecat instance.
238
+
239
+ ---
240
+
241
+ ## Roadmap
242
+
243
+ This project is under active development. Tracecat's API surface evolves fast, and we intend to keep up — expect new tools, refinements, and breaking-change adaptations as the platform matures.
244
+
245
+ Planned areas of improvement:
246
+
247
+ - **More tools** — covering new Tracecat API endpoints as they ship
248
+ - **Better error handling** — structured error responses with actionable hints
249
+ - **OAuth/OIDC support** — for Tracecat instances using SSO instead of basic auth
250
+ - **Test suite** — automated integration tests against a live Tracecat instance
251
+
252
+ Contributions, issues, and feature requests are welcome.
253
+
254
+ ---
255
+
256
+ ## Related Projects
257
+
258
+ - [tracecat-skills](https://github.com/adrojis/tracecat-skills) — Claude Code skills for Tracecat workflow building
259
+ > **Note:** This project was previously named `tracecat-mcp`. It has been renamed to `tracecat-mcp-community` to clearly distinguish it from [Tracecat's official MCP server](https://github.com/TracecatHQ/tracecat) which uses OAuth authentication.
260
+ - [Tracecat](https://github.com/TracecatHQ/tracecat) — The open-source SOAR platform
261
+ - [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) — Model Context Protocol TypeScript SDK
262
+
263
+ ---
264
+
265
+ ## License
266
+
267
+ [MIT](LICENSE)
@@ -0,0 +1,26 @@
1
+ export declare class TracecatClient {
2
+ private baseUrl;
3
+ private workspaceId;
4
+ private sessionCookie;
5
+ private username;
6
+ private password;
7
+ private initialized;
8
+ private initPromise;
9
+ constructor(baseUrl: string, username: string, password: string, workspaceId?: string);
10
+ /** Ensures the client is logged in and workspace is set. Safe to call multiple times. */
11
+ ensureInitialized(): Promise<void>;
12
+ login(): Promise<void>;
13
+ private headers;
14
+ request<T = unknown>(method: string, path: string, body?: unknown, queryParams?: Record<string, string>): Promise<T>;
15
+ get<T = unknown>(path: string, queryParams?: Record<string, string>): Promise<T>;
16
+ post<T = unknown>(path: string, body?: unknown, queryParams?: Record<string, string>): Promise<T>;
17
+ patch<T = unknown>(path: string, body: unknown, queryParams?: Record<string, string>): Promise<T>;
18
+ delete<T = unknown>(path: string, queryParams?: Record<string, string>): Promise<T>;
19
+ initWorkspaceId(): Promise<void>;
20
+ getWorkspaceId(): string;
21
+ /** Fetch current graph then apply operations with optimistic locking */
22
+ patchGraph(workflowId: string, operations: Array<{
23
+ type: string;
24
+ payload: Record<string, unknown>;
25
+ }>): Promise<unknown>;
26
+ }
package/dist/client.js ADDED
@@ -0,0 +1,147 @@
1
+ export class TracecatClient {
2
+ baseUrl;
3
+ workspaceId;
4
+ sessionCookie = "";
5
+ username;
6
+ password;
7
+ initialized = false;
8
+ initPromise = null;
9
+ constructor(baseUrl, username, password, workspaceId = "") {
10
+ this.baseUrl = baseUrl.replace(/\/$/, "");
11
+ this.username = username;
12
+ this.password = password;
13
+ this.workspaceId = workspaceId;
14
+ }
15
+ /** Ensures the client is logged in and workspace is set. Safe to call multiple times. */
16
+ async ensureInitialized() {
17
+ if (this.initialized)
18
+ return;
19
+ if (!this.initPromise) {
20
+ this.initPromise = (async () => {
21
+ await this.login();
22
+ await this.initWorkspaceId();
23
+ this.initialized = true;
24
+ console.error("[tracecat-mcp-community] Login successful");
25
+ console.error(`[tracecat-mcp-community] Workspace: ${this.workspaceId || "(none)"}`);
26
+ })();
27
+ }
28
+ await this.initPromise;
29
+ }
30
+ async login() {
31
+ const formData = new URLSearchParams();
32
+ formData.append("username", this.username);
33
+ formData.append("password", this.password);
34
+ const response = await fetch(`${this.baseUrl}/auth/login`, {
35
+ method: "POST",
36
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
37
+ body: formData.toString(),
38
+ redirect: "manual",
39
+ });
40
+ if (!response.ok && response.status !== 204 && response.status !== 302) {
41
+ throw new Error(`Login failed (${response.status}). Check your TRACECAT_USERNAME and TRACECAT_PASSWORD in .env`);
42
+ }
43
+ // Extract session cookie from set-cookie header
44
+ const setCookie = response.headers.getSetCookie?.() ?? [];
45
+ for (const cookie of setCookie) {
46
+ const match = cookie.match(/fastapiusersauth=([^;]+)/);
47
+ if (match) {
48
+ this.sessionCookie = match[1];
49
+ return;
50
+ }
51
+ }
52
+ // Fallback: try raw header
53
+ const rawSetCookie = response.headers.get("set-cookie") ?? "";
54
+ const match = rawSetCookie.match(/fastapiusersauth=([^;]+)/);
55
+ if (match) {
56
+ this.sessionCookie = match[1];
57
+ return;
58
+ }
59
+ throw new Error("Login succeeded but no session cookie received. " +
60
+ "Check that the Tracecat API is returning a 'fastapiusersauth' cookie.");
61
+ }
62
+ headers() {
63
+ return {
64
+ "Content-Type": "application/json",
65
+ Cookie: `fastapiusersauth=${this.sessionCookie}`,
66
+ };
67
+ }
68
+ async request(method, path, body, queryParams) {
69
+ await this.ensureInitialized();
70
+ // Auto-inject workspace_id on every request (skip auth/workspaces endpoints)
71
+ const params = new URLSearchParams(queryParams);
72
+ if (this.workspaceId && !path.startsWith("/auth") && path !== "/workspaces" && path !== "/ready") {
73
+ if (!params.has("workspace_id")) {
74
+ params.set("workspace_id", this.workspaceId);
75
+ }
76
+ }
77
+ let url = `${this.baseUrl}${path}`;
78
+ const qs = params.toString();
79
+ if (qs) {
80
+ url += `?${qs}`;
81
+ }
82
+ const options = {
83
+ method,
84
+ headers: this.headers(),
85
+ };
86
+ if (body !== undefined) {
87
+ options.body = JSON.stringify(body);
88
+ }
89
+ const response = await fetch(url, options);
90
+ if (!response.ok) {
91
+ const errorText = await response.text();
92
+ throw new Error(`Tracecat API error ${response.status}: ${errorText}`);
93
+ }
94
+ const contentType = response.headers.get("content-type");
95
+ if (contentType?.includes("application/json")) {
96
+ return (await response.json());
97
+ }
98
+ return (await response.text());
99
+ }
100
+ async get(path, queryParams) {
101
+ return this.request("GET", path, undefined, queryParams);
102
+ }
103
+ async post(path, body, queryParams) {
104
+ return this.request("POST", path, body, queryParams);
105
+ }
106
+ async patch(path, body, queryParams) {
107
+ return this.request("PATCH", path, body, queryParams);
108
+ }
109
+ async delete(path, queryParams) {
110
+ return this.request("DELETE", path, undefined, queryParams);
111
+ }
112
+ async initWorkspaceId() {
113
+ if (this.workspaceId)
114
+ return;
115
+ try {
116
+ // /workspaces doesn't need workspace_id
117
+ const response = await fetch(`${this.baseUrl}/workspaces`, {
118
+ headers: {
119
+ Cookie: `fastapiusersauth=${this.sessionCookie}`,
120
+ },
121
+ });
122
+ if (response.ok) {
123
+ const workspaces = (await response.json());
124
+ if (workspaces.length > 0) {
125
+ this.workspaceId = workspaces[0].id;
126
+ }
127
+ }
128
+ }
129
+ catch {
130
+ // Workspace ID will remain empty; some endpoints may not require it
131
+ }
132
+ }
133
+ getWorkspaceId() {
134
+ return this.workspaceId;
135
+ }
136
+ /** Fetch current graph then apply operations with optimistic locking */
137
+ async patchGraph(workflowId, operations) {
138
+ // 1. Get current graph to read base_version (version is at root level)
139
+ const graph = await this.get(`/workflows/${workflowId}/graph`);
140
+ const baseVersion = graph.version;
141
+ // 2. Patch with operations
142
+ return this.patch(`/workflows/${workflowId}/graph`, {
143
+ base_version: baseVersion,
144
+ operations,
145
+ });
146
+ }
147
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ import { config } from "dotenv";
3
+ import { fileURLToPath } from "url";
4
+ import { dirname, resolve } from "path";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { TracecatClient } from "./client.js";
7
+ import { createServer } from "./server.js";
8
+ // Load .env from the mcp_server directory (not cwd)
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+ config({ path: resolve(__dirname, "..", ".env") });
12
+ const apiUrl = process.env.TRACECAT_API_URL ?? "http://localhost/api";
13
+ const username = process.env.TRACECAT_USERNAME ?? "";
14
+ const password = process.env.TRACECAT_PASSWORD ?? "";
15
+ const workspaceId = process.env.TRACECAT_WORKSPACE_ID ?? "";
16
+ if (!username || !password) {
17
+ process.stderr.write("TRACECAT_USERNAME and TRACECAT_PASSWORD environment variables are required\n");
18
+ process.exit(1);
19
+ }
20
+ const client = new TracecatClient(apiUrl, username, password, workspaceId);
21
+ const server = createServer(client);
22
+ const transport = new StdioServerTransport();
23
+ // Start MCP transport immediately - login happens lazily on first tool call
24
+ server.connect(transport).then(() => {
25
+ process.stderr.write("[tracecat-mcp-community] MCP server ready (login will happen on first request)\n");
26
+ }).catch((error) => {
27
+ process.stderr.write(`[tracecat-mcp-community] Fatal error: ${error}\n`);
28
+ process.exit(1);
29
+ });
30
+ // Graceful shutdown
31
+ process.on("SIGINT", () => process.exit(0));
32
+ process.on("SIGTERM", () => process.exit(0));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ const server = new McpServer({ name: "tracecat", version: "1.0.0" });
4
+ server.tool("ping", "Returns pong", {}, async () => {
5
+ return { content: [{ type: "text", text: "pong" }] };
6
+ });
7
+ const transport = new StdioServerTransport();
8
+ server.connect(transport);
@@ -0,0 +1,8 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ const server = new McpServer({ name: "tracecat", version: "1.0.0" });
4
+ server.tool("ping", "Returns pong", {}, async () => {
5
+ return { content: [{ type: "text", text: "pong" }] };
6
+ });
7
+ const transport = new StdioServerTransport();
8
+ server.connect(transport);
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { TracecatClient } from "./client.js";
3
+ export declare function createServer(client: TracecatClient): McpServer;
package/dist/server.js ADDED
@@ -0,0 +1,32 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { registerWorkflowTools } from "./tools/workflows.js";
3
+ import { registerExecutionTools } from "./tools/executions.js";
4
+ import { registerCaseTools } from "./tools/cases.js";
5
+ import { registerActionTools } from "./tools/actions.js";
6
+ import { registerSecretTools } from "./tools/secrets.js";
7
+ import { registerTableTools } from "./tools/tables.js";
8
+ import { registerWebhookTools } from "./tools/webhooks.js";
9
+ import { registerSystemTools } from "./tools/system.js";
10
+ import { registerScheduleTools } from "./tools/schedules.js";
11
+ import { registerGraphTools } from "./tools/graph.js";
12
+ import { registerDocTools } from "./tools/docs.js";
13
+ import { registerTemplateTools } from "./tools/templates.js";
14
+ export function createServer(client) {
15
+ const server = new McpServer({
16
+ name: "tracecat",
17
+ version: "1.0.0",
18
+ });
19
+ registerWorkflowTools(server, client);
20
+ registerExecutionTools(server, client);
21
+ registerCaseTools(server, client);
22
+ registerActionTools(server, client);
23
+ registerSecretTools(server, client);
24
+ registerTableTools(server, client);
25
+ registerWebhookTools(server, client);
26
+ registerScheduleTools(server, client);
27
+ registerSystemTools(server, client);
28
+ registerGraphTools(server, client);
29
+ registerDocTools(server, client);
30
+ registerTemplateTools(server, client);
31
+ return server;
32
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { TracecatClient } from "../client.js";
3
+ export declare function registerActionTools(server: McpServer, client: TracecatClient): void;
@@ -0,0 +1,54 @@
1
+ import { z } from "zod";
2
+ export function registerActionTools(server, client) {
3
+ server.tool("tracecat_list_actions", "List all actions for a given workflow", {
4
+ workflow_id: z.string().describe("Workflow ID"),
5
+ }, async ({ workflow_id }) => {
6
+ const actions = await client.get(`/actions`, { workflow_id });
7
+ return { content: [{ type: "text", text: JSON.stringify(actions, null, 2) }] };
8
+ });
9
+ server.tool("tracecat_create_action", "Create a new action in a workflow", {
10
+ workflow_id: z.string().describe("Workflow ID"),
11
+ type: z.string().describe("Action type (e.g. core.transform.reshape, core.http.request, core.script.run_python)"),
12
+ title: z.string().describe("Action title"),
13
+ }, async ({ workflow_id, type, title }) => {
14
+ const result = await client.post(`/actions`, { workflow_id, type, title });
15
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
16
+ });
17
+ server.tool("tracecat_get_action", "Get details of a specific action by ID", {
18
+ action_id: z.string().describe("Action ID"),
19
+ workflow_id: z.string().describe("Workflow ID"),
20
+ }, async ({ action_id, workflow_id }) => {
21
+ const action = await client.get(`/actions/${action_id}`, { workflow_id });
22
+ return { content: [{ type: "text", text: JSON.stringify(action, null, 2) }] };
23
+ });
24
+ server.tool("tracecat_update_action", "Update an existing action (title, description, inputs, control_flow). Note: inputs must be a YAML string, not a JSON object.", {
25
+ action_id: z.string().describe("Action ID"),
26
+ workflow_id: z.string().describe("Workflow ID"),
27
+ title: z.string().optional().describe("New title"),
28
+ description: z.string().optional().describe("New description"),
29
+ inputs: z.string().optional().describe("Action inputs as a YAML string (e.g. 'value: hello\\nurl: https://...')"),
30
+ control_flow: z.object({
31
+ run_if: z.string().nullable().optional().describe("Conditional expression"),
32
+ for_each: z.string().nullable().optional().describe("Loop expression"),
33
+ join_strategy: z.string().optional().describe("'all' or 'any'"),
34
+ retry_policy: z.object({
35
+ max_attempts: z.number().optional(),
36
+ timeout: z.number().optional(),
37
+ retry_until: z.string().nullable().optional(),
38
+ }).optional(),
39
+ start_delay: z.number().optional().describe("Delay in seconds before execution"),
40
+ }).optional().describe("Control flow settings"),
41
+ }, async ({ action_id, workflow_id, ...updates }) => {
42
+ const body = Object.fromEntries(Object.entries(updates).filter(([, v]) => v !== undefined));
43
+ // Update uses POST, not PATCH
44
+ const result = await client.post(`/actions/${action_id}`, body, { workflow_id });
45
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
46
+ });
47
+ server.tool("tracecat_delete_action", "Delete an action from a workflow", {
48
+ action_id: z.string().describe("Action ID"),
49
+ workflow_id: z.string().describe("Workflow ID"),
50
+ }, async ({ action_id, workflow_id }) => {
51
+ const result = await client.delete(`/actions/${action_id}`, { workflow_id });
52
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
53
+ });
54
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { TracecatClient } from "../client.js";
3
+ export declare function registerCaseTools(server: McpServer, client: TracecatClient): void;