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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "activepieces",
"version": "0.79.1",
"rcVersion": "0.78.0-rc.0",
"version": "0.79.2",
"rcVersion": "0.80.0-rc.0",
"packageManager": "bun@1.3.3",
"scripts": {
"prebuild": "node tools/scripts/install-bun.js",
Expand Down
18 changes: 17 additions & 1 deletion packages/server/api/src/app/mcp/mcp-server-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,22 @@ export const mcpServerController: FastifyPluginAsyncTypebox = async (app) => {
})
})

app.get('/http', StreamableHttpRequestRequest, async (_req, reply) => {
return reply.status(405).send({
error: 'Method Not Allowed',
message: 'Use POST with Authorization: Bearer <token> for MCP requests.',
})
})

app.post('/http', StreamableHttpRequestRequest, async (req, reply) => {
const mcp = await mcpServerService(req.log).getPopulatedByProjectId(req.params.projectId)
const authHeader = req.headers['authorization']
if (!validateAuthorizationHeader(authHeader, mcp)) {
const tokenFromHeader = validateAuthorizationHeader(authHeader, mcp)
const tokenFromQuery = validateTokenFromQuery(req.query, mcp)
if (!tokenFromHeader && !tokenFromQuery) {
return reply.status(401).send({
error: 'Unauthorized',
message: 'Missing or invalid token. Use Authorization: Bearer <token> or add ?token=<token> to the URL (for clients that cannot send headers).',
})
}
const { server } = await mcpServerService(req.log).buildServer({
Expand Down Expand Up @@ -84,6 +94,12 @@ function validateAuthorizationHeader(authHeader: string | undefined, mcp: Popula
return type === 'Bearer' && token === mcp.token
}

function validateTokenFromQuery(query: unknown, mcp: PopulatedMcpServer) {
const queryParams = query as Record<string, string | undefined>
const token = queryParams.token
return token === mcp.token
}

function createTransportConfig(
protocol: McpProtocol,
serverUrl: string,
Expand Down
10 changes: 10 additions & 0 deletions packages/server/api/src/app/mcp/mcp-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,17 @@ export const mcpServerService = (log: FastifyBaseLogger) => {
buildServer: async ({ mcp }: BuildServerRequest): Promise<McpServer> => {
const server = new McpServer({
name: 'Activepieces',
title: 'Activepieces',
version: '1.0.0',
websiteUrl: 'https://activepieces.com',
description: 'Automation and workflow MCP server by Activepieces',
icons: [
{
src: 'https://cdn.activepieces.com/pieces/activepieces.png',
mimeType: 'image/png',
sizes: ['48x48', '96x96'],
},
],
})
const enabledFlows = mcp.flows.filter((flow) => flow.status === FlowStatus.ENABLED)
for (const flow of enabledFlows) {
Expand Down
Binary file added packages/web/public/favicon.ico
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ export function McpCredentials({ mcpServer }: McpCredentialsProps) {
},
};

const remote_mcp_server_url = `${serverUrl}?token=${encodeURIComponent(
mcpServer?.token ?? '',
)}`;

const customConnectorConfiguration = {
remote_mcp_server_url,
};

return (
<div className="space-y-4">
{/* Base URL Field */}
Expand Down Expand Up @@ -141,6 +149,16 @@ export function McpCredentials({ mcpServer }: McpCredentialsProps) {
)}
defaultOpen={false}
/>

{/* Custom Connector (no custom headers) */}
<CollapsibleJson
json={customConnectorConfiguration}
label={t('Claude Custom Connector')}
description={t(
"Only use connectors from developers you trust. The platform does not control which tools developers make available and cannot verify that they will work as intended or that they won't change.",
)}
defaultOpen={false}
/>
</div>
);
}
Expand Down
Loading