Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
0361250
feat(mcp): integrate MCP Library functionality
ashleymavericks Jan 7, 2026
fa767e6
feat(config-panel): add McpLibraryToolSelector component to ConfigPanel
ashleymavericks Jan 7, 2026
45d652e
feat(mcp): implement server connection testing and JSON import functi…
ashleymavericks Jan 8, 2026
56c81bd
refactor(mcp-library): update JSON import functionality and improve f…
ashleymavericks Jan 9, 2026
61d42d3
feat(mcp): add tool management functionality with toggle feature
ashleymavericks Jan 9, 2026
72a96a7
feat(mcp-library): enhance health check functionality and server stat…
ashleymavericks Jan 15, 2026
b74de62
feat(mcp): add MCP server management endpoints and encrypted headers …
ashleymavericks Jan 16, 2026
484cd35
Resolve MCP library merge conflicts
betterclever Feb 2, 2026
a637ea5
Update bun.lock after merge
betterclever Feb 2, 2026
f3487c5
fix: resolve merge conflicts and type errors after merging main
betterclever Feb 2, 2026
fda8ea9
docs: add MCP Library component design
betterclever Feb 2, 2026
4250bb9
feat: add MCP Library component for worker
betterclever Feb 2, 2026
c1e4b88
feat: add MCP Library UI components
betterclever Feb 2, 2026
a18a4f4
fix: add MCP Library component registration and fix tool mode parameters
betterclever Feb 2, 2026
4b4e738
refactor: remove legacy MCP HTTP provider and MCP tool merge components
betterclever Feb 2, 2026
f1b4315
feat: add MCP servers display to workflow node preview
betterclever Feb 2, 2026
e848570
feat: reimagine MCP library page
betterclever Feb 2, 2026
3ccf5c9
Revert "feat: reimagine MCP library page"
betterclever Feb 2, 2026
80cd7a6
fix: MCP group UI and tool discovery
betterclever Feb 2, 2026
c781f81
fix: include mcp server group ids
betterclever Feb 3, 2026
2f1d2ea
feat: import group templates with auto discovery
betterclever Feb 3, 2026
99bdc6e
feat: compact group cards and add group removal
betterclever Feb 3, 2026
dece3a1
fix: use logo dev for group icons and register aws group
betterclever Feb 3, 2026
8db6fa3
feat: merge group import into groups header
betterclever Feb 3, 2026
aa95982
feat: add import menu info and imported states
betterclever Feb 3, 2026
ede5206
chore: rename groups header
betterclever Feb 3, 2026
5794925
fix: delete group servers on group removal
betterclever Feb 3, 2026
6d985de
feat: add MCP Group dynamic server discovery and UI improvements
betterclever Feb 3, 2026
1032ed2
fix: update AWS MCP Group to output tools with mcp.tool contract
betterclever Feb 3, 2026
a4d5655
fix: resolve TypeScript errors in frontend
betterclever Feb 3, 2026
db220a4
feat: add collapsible Settings section to sidebar navigation
betterclever Feb 3, 2026
cebb87c
refactor: rename MCP Library to MCP Servers in navigation
betterclever Feb 3, 2026
b1664d9
refactor: rename Settings section to Manage in sidebar
betterclever Feb 3, 2026
c017898
refactor: rename MCP Library component to Custom MCPs
betterclever Feb 3, 2026
40b44a0
refactor: rename worker component from MCP Library to Custom MCPs
betterclever Feb 3, 2026
8c802d6
fix: filter out MCP group servers from Custom MCPs component
betterclever Feb 3, 2026
a7c7029
refactor: remove legacy MCP Server component
betterclever Feb 3, 2026
f89d302
feat: add secret references for MCP servers and fix TypeScript errors
betterclever Feb 3, 2026
9c7fe54
test: fix MCP Library integration tests after refactor
betterclever Feb 3, 2026
df21424
chore: remove temporary documentation files
betterclever Feb 3, 2026
5e6d83b
refactor: remove unused MCP client direct connection code
betterclever Feb 3, 2026
5d4c173
refactor: convert MCP DTOs to use nestjs-zod helpers
betterclever Feb 3, 2026
c93a498
chore: regenerate OpenAPI spec after DTO refactoring
betterclever Feb 3, 2026
ffe7bf9
chore: regenerate backend client and add lint ignores
betterclever Feb 3, 2026
78de3de
fix typecheck
betterclever Feb 3, 2026
be08ee1
remove the unneeded docs
betterclever Feb 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Auto-generated OpenAPI specification
openapi.json

# Build outputs
dist/
build/
*.tsbuildinfo

# Dependencies
node_modules/

# Generated files
*.generated.ts
13 changes: 13 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Auto-generated OpenAPI specification
openapi.json

# Build outputs
dist/
build/
*.tsbuildinfo

# Dependencies
node_modules/

# Generated files
*.generated.ts
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
</p>

# ShipSec Studio

**Open-Source Security Workflow Orchestration Platform.**

> ShipSec is currently in active development. We are optimizing the platform for stable production use and high-performance security operations.
ShipSec Studio provides a visual DSL and runtime for building, executing, and monitoring automated security workflows. It decouples security logic from infrastructure management, providing a durable and isolated environment for running security tooling at scale.


<div align="center">
<a href="https://youtu.be/7uyv43VforM">
<img src="https://img.youtube.com/vi/7uyv43VforM/maxresdefault.jpg" alt="ShipSec Studio Demo" width="600">
Expand All @@ -27,10 +27,10 @@ ShipSec Studio provides a visual DSL and runtime for building, executing, and mo

### 🏗️ Core Pillars

* **Durable, resumable workflows** powered by Temporal.io for stateful execution across failures.
* **Isolated security runtimes** using ephemeral containers with per-run volume management.
* **Unified telemetry streams** delivering terminal output, events, and logs via a low-latency SSE pipeline.
* **Visual no-code builder** that compiles complex security graphs into an executable DSL.
- **Durable, resumable workflows** powered by Temporal.io for stateful execution across failures.
- **Isolated security runtimes** using ephemeral containers with per-run volume management.
- **Unified telemetry streams** delivering terminal output, events, and logs via a low-latency SSE pipeline.
- **Visual no-code builder** that compiles complex security graphs into an executable DSL.

---

Expand All @@ -47,6 +47,7 @@ curl -fsSL https://raw.githubusercontent.com/ShipSecAI/studio/main/install.sh |
```

This installer will:

- Check and install missing dependencies (docker, just, curl, jq, git)
- Start Docker if not running
- Clone the repository and start all services
Expand All @@ -55,14 +56,18 @@ This installer will:
Once complete, visit **http://localhost:8090** to access ShipSec Studio.

### 2. ShipSec Cloud (Preview)

The fastest way to test ShipSec Studio without managing infrastructure.

- **Try it out:** [studio.shipsec.ai](https://studio.shipsec.ai)
- **Note:** ShipSec Studio is under active development. The cloud environment is a technical preview for evaluation and sandbox testing.

### 3. Self-Host (Docker)

For teams requiring data residency and air-gapped security orchestrations. This setup runs the full stack (Frontend, Backend, Worker, and Infrastructure).

**Prerequisites:**

- **[docker](https://www.docker.com/)** - For running the application and security components
- **[just](https://github.com/casey/just)** - Command runner for simplified workflows
- **curl** and **jq** - For fetching release information
Expand All @@ -73,24 +78,34 @@ git clone https://github.com/ShipSecAI/studio.git
cd studio
just prod start-latest
```

Access the studio at `http://localhost:8090`.

---

## 🛠️ Capabilities

### Integrated Tooling

Native support for industry-standard security tools including:

- **Discovery**: `Subfinder`, `DNSX`, `Naabu`, `HTTPx`
- **Vulnerability**: `Nuclei`, `TruffleHog`
- **Utility**: `JSON Transform`, `Logic Scripts`, `HTTP Requests`

### Advanced Orchestration

- **Human-in-the-Loop**: Pause workflows for approvals, form inputs, or manual validation before continuing.
- **AI-Driven Analysis**: Leverage LLM nodes and MCP providers for intelligent results interpretation.
- **Native Scheduling**: Integrated CRON support for recurring security posture and compliance monitoring.
- **API First**: Trigger and monitor any workflow execution via a comprehensive REST API.

### MCP Integration

- **MCP Library**: Centralized MCP server management with multi-server selection and automatic tool registration
- **Built-in MCP Servers**: AWS CloudTrail, CloudWatch, and Filesystem support out-of-the-box
- **Seamless Tool Discovery**: AI Agents automatically discover and use MCP tools via standardized contracts

---

## 🏛️ Architecture Overview
Expand Down Expand Up @@ -128,4 +143,3 @@ ShipSec Studio is licensed under the **Apache License 2.0**.
<div align="center">
<p>Engineered for security teams by the ShipSec AI team.</p>
</div>

4 changes: 4 additions & 0 deletions backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { McpModule } from './mcp/mcp.module';
import { ApiKeysModule } from './api-keys/api-keys.module';
import { WebhooksModule } from './webhooks/webhooks.module';
import { HumanInputsModule } from './human-inputs/human-inputs.module';
import { McpServersModule } from './mcp-servers/mcp-servers.module';
import { McpGroupsModule } from './mcp-groups/mcp-groups.module';

const coreModules = [
AgentsModule,
Expand All @@ -38,6 +40,8 @@ const coreModules = [
ApiKeysModule,
WebhooksModule,
HumanInputsModule,
McpServersModule,
McpGroupsModule,
McpModule,
];

Expand Down
2 changes: 2 additions & 0 deletions backend/src/database/schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ export * from './webhooks';

export * from './terminal-records';
export * from './agent-trace-events';
export * from './mcp-servers';

export * from './node-io';
172 changes: 172 additions & 0 deletions backend/src/database/schema/mcp-servers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import {
pgTable,
uuid,
varchar,
text,
timestamp,
jsonb,
boolean,
index,
uniqueIndex,
primaryKey,
} from 'drizzle-orm/pg-core';

/**
* MCP Groups table.
* Defines logical groupings of MCP servers with shared credentials and configurations.
* Groups provide a way to bundle servers that work well together (e.g., "GitHub Tools", "Data Analysis").
*/
export const mcpGroups = pgTable(
'mcp_groups',
{
id: uuid('id').primaryKey().defaultRandom(),
slug: varchar('slug', { length: 191 }).notNull().unique(),
name: varchar('name', { length: 191 }).notNull(),
description: text('description'),

// Credential configuration
credentialContractName: varchar('credential_contract_name', { length: 191 }).notNull(),
credentialMapping: jsonb('credential_mapping')
.$type<Record<string, unknown> | null>()
.default(null),

// Default Docker image for servers in this group
defaultDockerImage: varchar('default_docker_image', { length: 255 }),

// Template tracking (for seeded groups from templates)
templateHash: varchar('template_hash', { length: 64 }),

// Status
enabled: boolean('enabled').notNull().default(true),

// Timestamps
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
},
(table) => ({
slugIdx: index('mcp_groups_slug_idx').on(table.slug),
enabledIdx: index('mcp_groups_enabled_idx').on(table.enabled),
}),
);

/**
* MCP Server configurations table.
* Stores configuration for Model Context Protocol servers that can be used by AI agents.
*/
export const mcpServers = pgTable(
'mcp_servers',
{
id: uuid('id').primaryKey().defaultRandom(),
name: varchar('name', { length: 191 }).notNull(),
description: text('description'),

// Transport configuration
transportType: varchar('transport_type', { length: 32 }).notNull(), // 'http' | 'stdio' | 'sse' | 'websocket'
endpoint: text('endpoint'), // URL for http/sse/websocket transports
command: text('command'), // Command for stdio transport
args: jsonb('args').$type<string[] | null>().default(null), // Args for stdio command

// Authentication (encrypted using AES-256-GCM, same pattern as integrations)
headers: jsonb('headers')
.$type<{
ciphertext: string;
iv: string;
authTag: string;
keyId: string;
} | null>()
.default(null),

// Status and settings
enabled: boolean('enabled').notNull().default(true),
healthCheckUrl: text('health_check_url'), // Optional custom health endpoint

// Health tracking
lastHealthCheck: timestamp('last_health_check', { withTimezone: true }),
lastHealthStatus: varchar('last_health_status', { length: 32 }), // 'healthy' | 'unhealthy' | 'unknown'

// Group association (nullable - servers can exist independently)
groupId: uuid('group_id').references(() => mcpGroups.id, { onDelete: 'set null' }),

// Multi-tenancy
organizationId: varchar('organization_id', { length: 191 }),
createdBy: varchar('created_by', { length: 191 }),

// Timestamps
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
},
(table) => ({
orgIdx: index('mcp_servers_org_idx').on(table.organizationId),
enabledIdx: index('mcp_servers_enabled_idx').on(table.enabled),
groupIdx: index('mcp_servers_group_idx').on(table.groupId),
nameOrgUnique: uniqueIndex('mcp_servers_name_org_uidx').on(table.name, table.organizationId),
}),
);

/**
* MCP Group to Server junction table.
* Defines which servers belong to which groups, with metadata about recommendations
* and default selection behavior.
*/
export const mcpGroupServers = pgTable(
'mcp_group_servers',
{
groupId: uuid('group_id')
.notNull()
.references(() => mcpGroups.id, { onDelete: 'cascade' }),
serverId: uuid('server_id')
.notNull()
.references(() => mcpServers.id, { onDelete: 'cascade' }),

// Metadata about the relationship
recommended: boolean('recommended').notNull().default(false),
defaultSelected: boolean('default_selected').notNull().default(true),

// Timestamps
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
},
(table) => ({
pk: primaryKey({ columns: [table.groupId, table.serverId] }),
groupIdx: index('mcp_group_servers_group_idx').on(table.groupId),
serverIdx: index('mcp_group_servers_server_idx').on(table.serverId),
}),
);

/**
* Cached tool definitions discovered from MCP servers.
* Tools are discovered via the MCP protocol and cached here for quick lookup.
*/
export const mcpServerTools = pgTable(
'mcp_server_tools',
{
id: uuid('id').primaryKey().defaultRandom(),
serverId: uuid('server_id')
.notNull()
.references(() => mcpServers.id, { onDelete: 'cascade' }),
toolName: varchar('tool_name', { length: 191 }).notNull(),
description: text('description'),
inputSchema: jsonb('input_schema').$type<Record<string, unknown> | null>().default(null),
enabled: boolean('enabled').notNull().default(true),
discoveredAt: timestamp('discovered_at', { withTimezone: true }).defaultNow().notNull(),
},
(table) => ({
serverIdx: index('mcp_server_tools_server_idx').on(table.serverId),
serverToolUnique: uniqueIndex('mcp_server_tools_server_tool_uidx').on(
table.serverId,
table.toolName,
),
}),
);

// Type exports for use in repositories and services
export type McpGroupRecord = typeof mcpGroups.$inferSelect;
export type NewMcpGroupRecord = typeof mcpGroups.$inferInsert;

export type McpGroupServerRecord = typeof mcpGroupServers.$inferSelect;
export type NewMcpGroupServerRecord = typeof mcpGroupServers.$inferInsert;

export type McpServerRecord = typeof mcpServers.$inferSelect;
export type NewMcpServerRecord = typeof mcpServers.$inferInsert;

export type McpServerToolRecord = typeof mcpServerTools.$inferSelect;
export type NewMcpServerToolRecord = typeof mcpServerTools.$inferInsert;
Loading