Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions .agents/features/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Exposes an Activepieces project as a Model Context Protocol (MCP) server so that
- `packages/server/api/src/app/mcp/mcp-entity.ts` — McpServer entity
- `packages/server/api/src/app/mcp/tools/index.ts` — static tool exports
- `packages/server/api/src/app/mcp/oauth/` — OAuth 2.0 PKCE flow for MCP clients that require OAuth
- `packages/shared/src/lib/automation/mcp/mcp.ts` — McpServer schema, McpToolDefinition type, McpServerStatus enum
- `packages/shared/src/lib/automation/mcp/mcp.ts` — McpServer schema, McpToolDefinition type
- `packages/shared/src/lib/automation/mcp/mcp-oauth.ts` — MCP OAuth types
- `packages/web/src/app/components/project-settings/mcp-server/index.tsx` — project settings panel for MCP
- `packages/web/src/app/components/project-settings/mcp-server/mcp-credentials.tsx` — token display and rotate UI
Expand All @@ -27,7 +27,7 @@ Exposes an Activepieces project as a Model Context Protocol (MCP) server so that
- Cloud: available

## Domain Terms
- **McpServer** — the per-project MCP server record (status, token, enabledTools)
- **McpServer** — the per-project MCP server record (token, enabledTools)
- **Locked tools** — tools that are always active when the MCP server is enabled; cannot be disabled
- **Controllable tools** — tools that platform or project owners can enable/disable individually
- **Dynamic flow tools** — flows that use the MCP trigger piece and are registered as callable tools; tool name format is `{toolName}_{flowId[0..4]}`
Expand All @@ -37,7 +37,7 @@ Exposes an Activepieces project as a Model Context Protocol (MCP) server so that

## Entity

**McpServer**: id, projectId (UNIQUE — one per project), status (ENABLED/DISABLED), token (72-char auth), enabledTools[] (JSONB, nullable — defaults to ALL_CONTROLLABLE_TOOL_NAMES).
**McpServer**: id, projectId (UNIQUE — one per project), token (72-char auth), enabledTools[] (JSONB, nullable — defaults to ALL_CONTROLLABLE_TOOL_NAMES).

## Tools

Expand Down Expand Up @@ -72,7 +72,7 @@ Exposes an Activepieces project as a Model Context Protocol (MCP) server so that
## Endpoints

- `GET /v1/mcp/:projectId` — get MCP server config + populated flows
- `POST /v1/mcp/:projectId` — update status and/or enabledTools
- `POST /v1/mcp/:projectId` — update enabledTools
- `POST /v1/mcp/:projectId/rotate` — rotate auth token
- `POST /v1/mcp/:projectId/http` — StreamableHTTP MCP protocol endpoint (main protocol handler)

Expand Down
2 changes: 0 additions & 2 deletions packages/react-ui/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,6 @@
"Environment": "",
"Unsaved changes": "",
"Save Changes": "",
"Enable MCP Access": "",
"Allow external agents to read and trigger your project's flows securely.": "",
"Tools": "",
"Internal Tools": "",
"Control which built-in Activepieces tools are available to agents via this MCP server.": "",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { QueryRunner } from 'typeorm'
import { Migration } from '../../migration'

export class RemoveMcpServerStatus1790000000000 implements Migration {
name = 'RemoveMcpServerStatus1790000000000'
breaking = false
release = '0.82.1'
transaction = true

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE "mcp_server"
DROP COLUMN "status"
`)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE "mcp_server"
ADD COLUMN "status" varchar NOT NULL DEFAULT 'ENABLED'
`)
}
}
2 changes: 2 additions & 0 deletions packages/server/api/src/app/database/postgres-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ import { MakeChatConversationPlatformWide1787000000000 } from './migration/postg
import { AddSsoDomainVerification1787100000000 } from './migration/postgres/1787100000000-AddSsoDomainVerification'
import { AddPlatformMcpServer1788000000000 } from './migration/postgres/1788000000000-AddPlatformMcpServer'
import { MakeMcpOAuthProjectIdNullable1789000000000 } from './migration/postgres/1789000000000-MakeMcpOAuthProjectIdNullable'
import { RemoveMcpServerStatus1790000000000 } from './migration/postgres/1790000000000-RemoveMcpServerStatus'

const getSslConfig = (): boolean | TlsOptions => {
const useSsl = system.get(AppSystemProp.POSTGRES_USE_SSL)
Expand Down Expand Up @@ -757,6 +758,7 @@ export const getMigrations = (): (new () => Migration)[] => {
AddPlatformMcpServer1788000000000,
MakeMcpOAuthProjectIdNullable1789000000000,
MakeChatConversationPlatformWide1787000000000,
RemoveMcpServerStatus1790000000000,
]
return migrations
}
Expand Down
4 changes: 0 additions & 4 deletions packages/server/api/src/app/mcp/mcp-entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ export const McpServerEntity = new EntitySchema<McpServerWithSchema>({
type: String,
nullable: false,
},
status: {
type: String,
nullable: false,
},
token: {
type: String,
nullable: false,
Expand Down
3 changes: 1 addition & 2 deletions packages/server/api/src/app/mcp/mcp-platform-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ export const mcpPlatformController: FastifyPluginAsyncZod = async (app) => {
})

app.post('/', UpdatePlatformMcpRoute, async (req) => {
const { status, enabledTools } = req.body
const { enabledTools } = req.body
return mcpServerService(req.log).updatePlatform({
platformId: req.principal.platform.id,
status,
enabledTools,
})
})
Expand Down
3 changes: 1 addition & 2 deletions packages/server/api/src/app/mcp/mcp-server-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ export const mcpServerController: FastifyPluginAsyncZod = async (app) => {
})

app.post('/', UpdateMcpRequest, async (req) => {
const { status, enabledTools } = req.body
const { enabledTools } = req.body
return mcpServerService(req.log).update({
projectId: req.projectId,
status,
enabledTools,
})
})
Expand Down
32 changes: 12 additions & 20 deletions packages/server/api/src/app/mcp/mcp-service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { apId, FlowTriggerType, FlowVersionState, isNil, MCP_TRIGGER_PIECE_NAME, McpServer as McpServerSchema, McpServerStatus, McpServerType, PopulatedFlow, PopulatedMcpServer, spreadIfNotUndefined, tryCatch } from '@activepieces/shared'
import { apId, FlowTriggerType, FlowVersionState, isNil, MCP_TRIGGER_PIECE_NAME, McpServer as McpServerSchema, McpServerType, PopulatedFlow, PopulatedMcpServer, tryCatch } from '@activepieces/shared'
import { FastifyBaseLogger } from 'fastify'
import { repoFactory } from '../core/db/repo-factory'
import { flowService } from '../flows/flow/flow.service'
Expand All @@ -12,14 +12,14 @@ export const mcpServerService = (log: FastifyBaseLogger) => ({
getByProjectId: async (projectId: string): Promise<McpServerSchema> => {
return getOrCreate({
where: { projectId },
defaults: { type: McpServerType.PROJECT, status: McpServerStatus.DISABLED, projectId, platformId: null },
defaults: { type: McpServerType.PROJECT, projectId, platformId: null },
})
},

getByPlatformId: async (platformId: string): Promise<McpServerSchema> => {
return getOrCreate({
where: { platformId },
defaults: { type: McpServerType.PLATFORM, status: McpServerStatus.ENABLED, platformId, projectId: null },
defaults: { type: McpServerType.PLATFORM, platformId, projectId: null },
})
},

Expand All @@ -46,15 +46,19 @@ export const mcpServerService = (log: FastifyBaseLogger) => ({
return mcpServerService(log).getByPlatformId(platformId)
},

update: async ({ projectId, status, enabledTools }: UpdateParams): Promise<PopulatedMcpServer> => {
update: async ({ projectId, enabledTools }: UpdateParams): Promise<PopulatedMcpServer> => {
const mcp = await mcpServerService(log).getByProjectId(projectId)
await applyPatch(mcp.id, { status, enabledTools })
if (!isNil(enabledTools)) {
await mcpServerRepository().update(mcp.id, { enabledTools })
}
return mcpServerService(log).getPopulatedByProjectId(projectId)
},

updatePlatform: async ({ platformId, status, enabledTools }: UpdatePlatformParams): Promise<McpServerSchema> => {
updatePlatform: async ({ platformId, enabledTools }: UpdatePlatformParams): Promise<McpServerSchema> => {
const mcp = await mcpServerService(log).getByPlatformId(platformId)
await applyPatch(mcp.id, { status, enabledTools })
if (!isNil(enabledTools)) {
await mcpServerRepository().update(mcp.id, { enabledTools })
}
return mcpServerService(log).getByPlatformId(platformId)
},

Expand All @@ -70,7 +74,7 @@ export const mcpServerService = (log: FastifyBaseLogger) => ({

async function getOrCreate({ where, defaults }: {
where: { projectId: string } | { platformId: string }
defaults: { type: McpServerType, status: McpServerStatus, projectId: string | null, platformId: string | null }
defaults: { type: McpServerType, projectId: string | null, platformId: string | null }
}): Promise<McpServerSchema> {
const existing = await mcpServerRepository().findOneBy(where)
if (!isNil(existing)) return existing
Expand All @@ -91,16 +95,6 @@ async function getOrCreate({ where, defaults }: {
return created
}

async function applyPatch(id: string, { status, enabledTools }: { status?: McpServerStatus, enabledTools?: string[] }): Promise<void> {
const patch = {
...spreadIfNotUndefined('status', status),
...spreadIfNotUndefined('enabledTools', enabledTools),
}
if (Object.keys(patch).length > 0) {
await mcpServerRepository().update(id, patch)
}
}

async function listMcpFlows(projectId: string, logger: FastifyBaseLogger): Promise<PopulatedFlow[]> {
const flows = await flowService(logger).list({
projectIds: [projectId],
Expand All @@ -114,12 +108,10 @@ async function listMcpFlows(projectId: string, logger: FastifyBaseLogger): Promi

type UpdateParams = {
projectId: string
status?: McpServerStatus
enabledTools?: string[]
}

type UpdatePlatformParams = {
platformId: string
status?: McpServerStatus
enabledTools?: string[]
}
2 changes: 0 additions & 2 deletions packages/server/api/test/integration/ce/mcp/mcp-tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
FlowActionType,
FlowRunStatus,
McpServer,
McpServerStatus,
PackageType,
PieceType,
RunEnvironment,
Expand Down Expand Up @@ -152,7 +151,6 @@ function makeMcp(projectId: string): McpServer {
created: new Date().toISOString(),
updated: new Date().toISOString(),
projectId,
status: McpServerStatus.ENABLED,
token: apId(),
enabledTools: null,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
apId,
FilteredPieceBehavior,
McpServer,
McpServerStatus,
PackageType,
PieceType,
} from '@activepieces/shared'
Expand Down Expand Up @@ -95,7 +94,6 @@ function makeMcp(projectId: string): McpServer {
created: new Date().toISOString(),
updated: new Date().toISOString(),
projectId,
status: McpServerStatus.ENABLED,
token: apId(),
enabledTools: null,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { FastifyBaseLogger, FastifyInstance } from 'fastify'
import {
apId,
DefaultProjectRole,
McpServerStatus,
McpServerType,
Permission,
ProjectScopedMcpServer,
Expand Down Expand Up @@ -35,7 +34,6 @@ function makeMcp(projectId: string): ProjectScopedMcpServer {
projectId,
platformId: null,
type: McpServerType.PROJECT,
status: McpServerStatus.ENABLED,
token: apId(),
enabledTools: null,
}
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@activepieces/shared",
"version": "0.71.1",
"version": "0.71.2",
"type": "commonjs",
"sideEffects": false,
"main": "./dist/src/index.js",
Expand Down
7 changes: 0 additions & 7 deletions packages/shared/src/lib/automation/mcp/mcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ export type McpId = ApId

export const MCP_TRIGGER_PIECE_NAME = '@activepieces/piece-mcp'

export enum McpServerStatus {
ENABLED = 'ENABLED',
DISABLED = 'DISABLED',
}

export enum McpServerType {
PLATFORM = 'PLATFORM',
PROJECT = 'PROJECT',
Expand All @@ -23,7 +18,6 @@ export const McpServer = z.object({
platformId: ApId.nullable(),
projectId: ApId.nullable(),
type: z.enum([McpServerType.PLATFORM, McpServerType.PROJECT]),
status: z.nativeEnum(McpServerStatus),
token: ApId,
enabledTools: z.array(z.string()).nullable(),
})
Expand All @@ -38,7 +32,6 @@ export type McpServer = z.infer<typeof McpServer>
export type ProjectScopedMcpServer = McpServer & { projectId: string }

export const UpdateMcpServerRequest = z.object({
status: z.nativeEnum(McpServerStatus).optional(),
enabledTools: z.array(z.string()).optional(),
})

Expand Down
13 changes: 11 additions & 2 deletions packages/web/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,6 @@
"Environment": "",
"Unsaved changes": "",
"Save Changes": "",
"Enable MCP Access": "",
"Allow external agents to read and trigger your project's flows securely.": "",
"Connection Details": "",
"Available Flows": "",
"Any flow that has the \"MCP Trigger\" turned on will show up here and can be accessed from your MCP server.": "",
Expand Down Expand Up @@ -1555,6 +1553,10 @@
"Build this automation": "Build this automation",
"Completed all steps": "Completed all steps",
"Connect {name}": "Connect {name}",
"Connect another": "Connect another",
"Use this account": "Use this account",
"Using {name}": "Using {name}",
"{count, plural, =1 {1 account already connected} other {# accounts already connected}}": "{count, plural, =1 {1 account already connected} other {# accounts already connected}}",
"Go to AI Settings": "Go to AI Settings",
"Help me connect two apps": "Help me connect two apps",
"I keep doing something manually...": "I keep doing something manually...",
Expand All @@ -1567,7 +1569,14 @@
"Brainstorm ideas": "Brainstorm ideas",
"Show thinking": "Show thinking",
"Hide thinking": "Hide thinking",
"Thoughts": "Thoughts",
"{current} of {total}": "{current} of {total}",
"Answers submitted": "Answers submitted",
"Type your answer...": "Type your answer...",
"Skip these questions": "Skip these questions",
"Release to add files to your message": "Release to add files to your message",
"Stop": "Stop",
"What can I do for you?": "What can I do for you?",
"New chat": "New chat",
"New conversation": "New conversation",
"Private Chat": "Private Chat",
Expand Down
Loading
Loading