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
7 changes: 2 additions & 5 deletions apps/api/src/handlers/mcp/__tests__/asana-auth.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions apps/api/src/handlers/mcp/__tests__/grafana-auth.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions apps/api/src/handlers/mcp/__tests__/granola-auth.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions apps/api/src/handlers/mcp/__tests__/notion-auth.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions apps/api/src/handlers/mcp/__tests__/snowflake-auth.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions apps/api/src/handlers/mcp/__tests__/vercel-auth.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion apps/api/src/handlers/mcp/asana/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ async function resolveAsanaMcpAuth(
};
}

if (authContext.tokenType === 'auth') {
return { userId: authContext.userId, tokenType: 'auth' };
}

throw new McpProxyError(
403,
'Asana MCP requires a task run token for server-side credential access',
'Asana MCP requires a user auth token or task run token for server-side credential access',
);
}

Expand Down
3 changes: 2 additions & 1 deletion apps/api/src/handlers/mcp/gbrain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ export const GBRAIN_READ_TOOL_NAMES = [
* upstream. Requests are refused unless the integration is enabled and a
* connection (admin-entered or env-pinned) exists.
*/
export function createGbrainMcpProxy() {
export function createGbrainMcpProxy(options?: { allowAuthTokens?: boolean }) {
return createMcpProxy({
name: 'Brain',
allowAuthTokens: options?.allowAuthTokens,
allowedToolNames: GBRAIN_READ_TOOL_NAMES,
validateTaskRunToken: async () => null,
resolveCredentials: async () => {
Expand Down
6 changes: 5 additions & 1 deletion apps/api/src/handlers/mcp/grafana/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ async function resolveGrafanaMcpAuth(
};
}

if (authContext.tokenType === 'auth') {
return { userId: authContext.userId, tokenType: 'auth' };
}

throw new McpProxyError(
403,
'Grafana MCP requires a task run token for server-side credential access',
'Grafana MCP requires a user auth token or task run token for server-side credential access',
);
}

Expand Down
6 changes: 5 additions & 1 deletion apps/api/src/handlers/mcp/granola/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ async function resolveGranolaMcpAuth(
};
}

if (authContext.tokenType === 'auth') {
return { userId: authContext.userId, tokenType: 'auth' };
}

throw new McpProxyError(
403,
'Granola MCP requires a task run token for server-side credential access',
'Granola MCP requires a user auth token or task run token for server-side credential access',
);
}

Expand Down
16 changes: 9 additions & 7 deletions apps/api/src/handlers/mcp/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
isCustomMcpDisabled,
} from '@roomote/env';
import {
getMcpIntegrationConnectionScope,
isCredentialOnlyMcpIntegration,
isNativeMcpIntegration,
MCP_INTEGRATIONS,
Expand All @@ -23,7 +24,7 @@ import { createIntegrationMcpProxy } from './integration-mcp';
import { granolaMcp } from './granola';
import { grafanaMcp } from './grafana';
import { getIntegrationMcpProxyOptions } from './integration-mcp-policy';
import { linearMcp } from './linear';
import { createLinearMcp } from './linear';
import { mcpAuthMiddleware } from './middleware';
import { notionMcp } from './notion';
import { slackMcp } from './slack';
Expand Down Expand Up @@ -67,12 +68,12 @@ mcp.route('/custom/:serverId', createCustomMcpProxy());
// integration with a custom handler, like snowflake/grafana below. The
// handler 404s per request unless the integration is enabled and a
// connection (admin-entered or R_GBRAIN_* env) exists.
mcp.route('/gbrain', createGbrainMcpProxy());
mcp.route('/gbrain', createGbrainMcpProxy({ allowAuthTokens: true }));

mcp.route('/asana', asanaMcp);
mcp.route('/granola', granolaMcp);
mcp.route('/grafana', grafanaMcp);
mcp.route('/linear', linearMcp);
mcp.route('/linear', createLinearMcp({ allowAuthTokens: true }));
mcp.route('/notion', notionMcp);
mcp.route('/snowflake', snowflakeMcp);
mcp.route('/vercel', vercelMcp);
Expand All @@ -85,10 +86,11 @@ for (const integration of MCP_INTEGRATIONS.filter(
)) {
mcp.route(
`/${integration.id}`,
createIntegrationMcpProxy(
integration,
getIntegrationMcpProxyOptions(integration),
),
createIntegrationMcpProxy(integration, {
...getIntegrationMcpProxyOptions(integration),
allowAuthTokens:
getMcpIntegrationConnectionScope(integration) === 'deployment',
}),
);
}

Expand Down
2 changes: 0 additions & 2 deletions apps/api/src/handlers/mcp/linear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,3 @@ export function createLinearMcp(options?: {
},
});
}

export const linearMcp = createLinearMcp();
6 changes: 5 additions & 1 deletion apps/api/src/handlers/mcp/notion/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,13 @@ async function resolveNotionMcpAuth(
};
}

if (authContext.tokenType === 'auth') {
return { userId: authContext.userId, tokenType: 'auth' };
}

throw new McpProxyError(
403,
'Notion MCP requires a task run token for server-side credential access',
'Notion MCP requires a user auth token or task run token for server-side credential access',
);
}

Expand Down
6 changes: 5 additions & 1 deletion apps/api/src/handlers/mcp/snowflake/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ async function resolveSnowflakeMcpAuth(
};
}

if (authContext.tokenType === 'auth') {
return { userId: authContext.userId, tokenType: 'auth' };
}

throw new McpProxyError(
403,
'Snowflake MCP requires a task run token for server-side credential access',
'Snowflake MCP requires a user auth token or task run token for server-side credential access',
);
}

Expand Down
6 changes: 5 additions & 1 deletion apps/api/src/handlers/mcp/vercel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ async function resolveVercelMcpAuth(
};
}

if (authContext.tokenType === 'auth') {
return { userId: authContext.userId, tokenType: 'auth' };
}

throw new McpProxyError(
403,
'Vercel MCP requires a task run token for server-side credential access',
'Vercel MCP requires a user auth token or task run token for server-side credential access',
);
}

Expand Down
8 changes: 8 additions & 0 deletions apps/api/src/handlers/slack/__tests__/fast-agent.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading