Skip to content

Conversation

@aline-pereira
Copy link

@aline-pereira aline-pereira commented Dec 29, 2025

Summary by cubic

Initial Grain MCP implementation to browse and fetch Grain meeting recordings via MCP. Adds list/search and per-recording detail tools with API-key auth, plus automatic webhooks and database indexing.

  • New Features

    • MCP server with Grain API client, types, and two tools: LIST_RECORDINGS and GET_RECORDING.
    • Listing supports limit/offset, date range, status, and search; returns titles, owners, duration, summaries, transcript URLs, notes, and cursor.
    • GET returns detailed recording info including summary points, transcript segments, highlights, and asset URLs.
    • Automatic webhook setup; incoming recording events are indexed into Postgres via the DATABASE binding.
    • HTTP app connection (app.json) with DATABASE binding.
  • Migration

    • Use a Grain API key as Authorization: Bearer when connecting.
    • Webhooks are auto-created; ensure the DATABASE binding is available in production.
    • Install and run: bun install; bun run dev. Publish/register via app.json if needed.

Written for commit ff00cee. Summary will update on new commits.

@github-actions
Copy link

github-actions bot commented Dec 29, 2025

🚀 Preview Deployments Ready!

Your changes have been deployed to preview environments:

📦 grain

🔗 View Preview

These previews will be automatically updated with new commits to this PR.


Deployed from commit: 65d786c

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 16 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="grain/test-api.ts">

<violation number="1" location="grain/test-api.ts:9">
P0: **Critical Security Issue**: Hardcoded API key committed to repository. This secret is now exposed in git history and should be immediately revoked. Use the commented-out environment variable approach instead (`process.env.GRAIN_API_KEY`).</violation>
</file>

Reply to cubic to teach it or ask questions. Tag @cubic-dev-ai to re-run a review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 11 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="grain/server/lib/grain-client.ts">

<violation number="1" location="grain/server/lib/grain-client.ts:174">
P2: The new webhook methods duplicate fetch and error-handling logic instead of reusing the existing `get`/`post` helpers. Consider extending the helpers to accept an `includeApiVersion` parameter rather than bypassing them, which would improve maintainability.</violation>
</file>

<file name="grain/server/lib/postgres.ts">

<violation number="1" location="grain/server/lib/postgres.ts:28">
P1: Manual SQL escaping is problematic here. If `DATABASES_RUN_SQL` uses proper parameterized queries (which its API signature suggests), this escaping is unnecessary and could cause double-escaping issues. If it doesn&#39;t parameterize properly, this escaping is incomplete and gives a false sense of security.

Remove the manual sanitization and rely on the database binding&#39;s parameterization, or verify how `DATABASES_RUN_SQL` handles parameters.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="grain/server/lib/postgres.ts">

<violation number="1" location="grain/server/lib/postgres.ts:29">
P1: Missing null check on `response` after optional chaining. If `MESH_REQUEST_CONTEXT` or `state` is undefined, `response` will be `undefined`, and accessing `response.result` will throw a runtime error. Either add a null check or throw a meaningful error if the database binding is unavailable.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 3 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="grain/server/main.ts">

<violation number="1" location="grain/server/main.ts:63">
P2: Error handling wraps entire loop - one failing event prevents processing of all subsequent events. Consider moving try-catch inside the loop to handle each event independently and continue processing.</violation>
</file>

<file name="grain/app.json">

<violation number="1" location="grain/app.json:10">
P0: Removing the `DATABASE` binding will break webhook-based recording indexing. The server code (`server/main.ts` and `server/lib/postgres.ts`) still expects this binding to access `@deco/postgres` for indexing recordings. Either restore the binding or remove the database-dependent code.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

try {
console.log("[GRAIN_MCP] Handling events:", events.length);

for (const event of events) {
Copy link

@cubic-dev-ai cubic-dev-ai bot Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Error handling wraps entire loop - one failing event prevents processing of all subsequent events. Consider moving try-catch inside the loop to handle each event independently and continue processing.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At grain/server/main.ts, line 63:

<comment>Error handling wraps entire loop - one failing event prevents processing of all subsequent events. Consider moving try-catch inside the loop to handle each event independently and continue processing.</comment>

<file context>
@@ -46,7 +47,46 @@ export interface Registry extends BindingRegistry {
+        try {
+          console.log(&quot;[GRAIN_MCP] Handling events:&quot;, events.length);
+
+          for (const event of events) {
+            console.log(&quot;[GRAIN_MCP] Processing event:&quot;, {
+              type: event.type,
</file context>
Fix with Cubic


const grainClient = new GrainClient({ apiKey: grainToken });

const webhookUrl = `${meshUrl}/events/grain_recording?sub=${connectionId}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const webhookUrl = `${meshUrl}/events/grain_recording?sub=${connectionId}`;
const orgId = env.MESH_REQUEST_CONTEXT?.organizationId;
const webhookUrl = `${meshUrl}/org/${orgId}/events/grain_recording?sub=${connectionId}`;

/**
* Event names that this MCP handles
*/
export const GRAIN_EVENTS = ["grain_recording"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const GRAIN_EVENTS = ["grain_recording"];
export const GRAIN_EVENTS = ["public:grain_recording"];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants