-
Notifications
You must be signed in to change notification settings - Fork 0
feat: added grain mcp initial implementation #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
aline-pereira
wants to merge
5
commits into
main
Choose a base branch
from
feat/grain-mcp
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
0ab23a6
feat: added grain mcp initial implementation
aline-pereira 193dbe6
added webhook and indexing
aline-pereira 08a7b2c
updated database env
aline-pereira 4ce7fb6
added event to runtime
aline-pereira ff00cee
initial refactor
aline-pereira File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| # Grain MCP | ||
|
|
||
| Access and manage your Grain meeting recordings through the Model Context Protocol. | ||
|
|
||
| ## Overview | ||
|
|
||
| The Grain MCP provides seamless integration with [Grain](https://grain.com), allowing AI assistants and applications to access your meeting recordings, transcripts, and summaries. Grain automatically records, transcribes, and summarizes your meetings, and this MCP makes that data accessible through a standardized interface. | ||
|
|
||
| ## Features | ||
|
|
||
| - 📝 **List Recordings**: Browse all your meeting recordings with powerful filtering options | ||
| - 🔍 **Search**: Find specific meetings by keywords, dates, or participants | ||
| - 📊 **Rich Metadata**: Access titles, dates, durations, participants, and summaries | ||
| - 🎯 **Filter by Status**: View only ready recordings or check processing status | ||
| - 📅 **Date Range Filtering**: Find meetings within specific time periods | ||
| - 🔔 **Real-time Webhooks**: Receive automatic notifications when recordings are created, updated, or processed | ||
|
|
||
| ## Authentication | ||
|
|
||
| This MCP uses API Key authentication. To get your Grain API key: | ||
|
|
||
| 1. Go to [Grain Settings - API](https://grain.com/settings/api) | ||
| 2. Click "Generate API Key" | ||
| 3. Copy the generated API key | ||
| 4. Provide it when connecting to this MCP | ||
|
|
||
| **Note**: Keep your API key secure and don't share it with others. | ||
|
|
||
| ## Tools | ||
|
|
||
| ### 1. LIST_RECORDINGS | ||
|
|
||
| List and search through your Grain meeting recordings with flexible filtering options. | ||
|
|
||
| **Input Parameters:** | ||
| - `limit` (optional): Maximum number of recordings to return (1-100, default: 50) | ||
| - `offset` (optional): Number of recordings to skip for pagination (default: 0) | ||
| - `start_date` (optional): Filter recordings from this date onwards (ISO 8601 format) | ||
| - `end_date` (optional): Filter recordings up to this date (ISO 8601 format) | ||
| - `status` (optional): Filter by status: "processing", "ready", or "failed" | ||
| - `search` (optional): Search by title, transcript, or participant names | ||
|
|
||
| **Output:** | ||
| - `recordings`: Array of recording objects with details | ||
| - `total`: Total number of recordings matching the query | ||
| - `limit`: Results per page | ||
| - `offset`: Current pagination offset | ||
| - `has_more`: Whether more results are available | ||
|
|
||
| **Example Usage:** | ||
|
|
||
| ```typescript | ||
| // List recent recordings | ||
| { | ||
| "limit": 10, | ||
| "status": "ready" | ||
| } | ||
|
|
||
| // Search for specific meetings | ||
| { | ||
| "search": "product roadmap", | ||
| "start_date": "2024-01-01" | ||
| } | ||
|
|
||
| // Get recordings from a date range | ||
| { | ||
| "start_date": "2024-01-01", | ||
| "end_date": "2024-01-31", | ||
| "limit": 20 | ||
| } | ||
| ``` | ||
|
|
||
| ### 2. GET_RECORDING | ||
|
|
||
| Get detailed information about a specific Grain recording by its ID. Returns comprehensive details including full transcript, AI summary, highlights, and more. | ||
|
|
||
| **Input Parameters:** | ||
| - `recordingId` (required): The unique identifier of the recording (e.g., "rec_abc123") | ||
|
|
||
| **Output:** | ||
| Returns a detailed recording object with all available information including: | ||
| - Basic info (id, title, date, duration, status) | ||
| - Participants with roles and emails | ||
| - Full transcript text | ||
| - Timestamped transcript segments with speaker attribution | ||
| - AI-generated summary | ||
| - User-created highlights and bookmarks | ||
| - Tags and metadata | ||
| - URLs to view in Grain | ||
|
|
||
| **Example Usage:** | ||
|
|
||
| ```typescript | ||
| // Get details of a specific recording | ||
| { | ||
| "recordingId": "rec_abc123" | ||
| } | ||
| ``` | ||
|
|
||
| ## Recording Object Structure | ||
|
|
||
| Each recording object includes: | ||
|
|
||
| ```typescript | ||
| { | ||
| id: string; // Unique identifier | ||
| title: string; // Meeting title | ||
| date: string; // Recording date (ISO 8601) | ||
| duration: number; // Duration in seconds | ||
| status: string; // "processing" | "ready" | "failed" | ||
| participants?: Array<{ // Meeting participants | ||
| id: string; | ||
| name: string; | ||
| email?: string; | ||
| role?: string; | ||
| }>; | ||
| summary?: string; // AI-generated summary | ||
| meeting_url?: string; // URL to view in Grain | ||
| recording_url?: string; // Direct recording URL | ||
| created_at: string; // Creation timestamp | ||
| updated_at: string; // Last update timestamp | ||
| } | ||
| ``` | ||
|
|
||
| ## Webhooks | ||
|
|
||
| This MCP automatically sets up webhooks with Grain to receive real-time notifications about your recordings. When you install or configure this MCP, it will: | ||
|
|
||
| 1. **Automatically create webhooks** pointing to the Deco Mesh | ||
| 2. **Listen for events** such as: | ||
| - `recording.created` - When a new recording starts | ||
| - `recording.updated` - When recording metadata changes | ||
| - `recording.processed` - When transcription and AI processing completes | ||
|
|
||
| 3. **Process events** through the `eventHandler` where you can add custom logic | ||
|
|
||
| ### How Webhooks Work | ||
|
|
||
| ``` | ||
| Grain Event → Grain API → Mesh → Your MCP → Custom Logic | ||
| ``` | ||
|
|
||
| The webhook URL is automatically constructed as: | ||
| ``` | ||
| ${meshUrl}/events/grain_recording?sub=${connectionId} | ||
| ``` | ||
|
|
||
| This ensures events are routed to your specific MCP instance. | ||
|
|
||
| ## Use Cases | ||
|
|
||
| ### Meeting Analytics | ||
| Analyze your meeting patterns, participant engagement, and time distribution across different types of meetings. | ||
|
|
||
| ### Knowledge Base Search | ||
| Search through all your meeting transcripts to find when specific topics were discussed or decisions were made. | ||
|
|
||
| ### Automated Summaries | ||
| Access AI-generated summaries of your meetings to quickly review what was discussed without watching the entire recording. | ||
|
|
||
| ### Follow-up Automation | ||
| Identify meetings that require follow-up based on participants, topics, or action items mentioned. | ||
|
|
||
| ### Team Insights | ||
| Track team collaboration by analyzing who attends which meetings and how often different people interact. | ||
|
|
||
| ### Real-time Notifications | ||
| Get instant alerts when new recordings are ready, enabling immediate action on important meetings. | ||
|
|
||
| ## API Reference | ||
|
|
||
| The Grain API uses the following structure: | ||
| - **Base URL**: `https://api.grain.com` | ||
| - **List Recordings**: `GET /_/public-api/recordings` (note: one underscore, not two) | ||
| - **Get Recording**: `GET /_/public-api/recordings/{id}` | ||
| - **Authentication**: Bearer token in Authorization header | ||
|
|
||
| For detailed information about the Grain API, visit: | ||
| - [Grain Developer Documentation](https://developers.grain.com/) | ||
| - [API Reference](https://developers.grain.com/api-reference) | ||
|
|
||
| ## Support | ||
|
|
||
| For issues or questions: | ||
| - Grain Support: [[email protected]](mailto:[email protected]) | ||
| - Grain Documentation: [https://help.grain.com](https://help.grain.com) | ||
|
|
||
| ## Development | ||
|
|
||
| ### Setup | ||
|
|
||
| ```bash | ||
| # Install dependencies | ||
| bun install | ||
|
|
||
| # Run in development mode | ||
| bun run dev | ||
|
|
||
| # Type check | ||
| bun run check | ||
|
|
||
| # Build for production | ||
| bun run build | ||
| ``` | ||
|
|
||
| ### Project Structure | ||
|
|
||
| ``` | ||
| grain/ | ||
| ├── server/ | ||
| │ ├── main.ts # MCP server entry point | ||
| │ ├── constants.ts # API constants | ||
| │ ├── lib/ | ||
| │ │ ├── grain-client.ts # Grain API client | ||
| │ │ ├── types.ts # TypeScript types | ||
| │ │ └── env.ts # Environment helpers | ||
| │ └── tools/ | ||
| │ ├── index.ts # Tools export | ||
| │ └── list-recordings.ts # List recordings tool | ||
| ├── package.json | ||
| ├── tsconfig.json | ||
| ├── app.json | ||
| └── README.md | ||
| ``` | ||
|
|
||
| ## License | ||
|
|
||
| This MCP is part of the Deco MCP collection and follows the same licensing terms. | ||
|
|
||
| ## Contributing | ||
|
|
||
| Contributions are welcome! Please ensure your code follows the existing patterns and includes appropriate tests. | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| { | ||
| "scopeName": "deco", | ||
| "name": "grain", | ||
| "connection": { | ||
| "type": "HTTP", | ||
| "url": "https://sites-grain.decocache.com/mcp" | ||
| }, | ||
| "description": "Grain App Connection - Access and manage your meeting recordings", | ||
| "icon": "https://grain.com/favicon.ico", | ||
| "unlisted": false, | ||
| "bindings": { | ||
| "DATABASE": "@deco/postgres" | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| { | ||
| "name": "grain", | ||
| "version": "1.0.0", | ||
| "description": "Grain MCP - Access and manage your Grain recordings and meetings", | ||
| "private": true, | ||
| "type": "module", | ||
| "scripts": { | ||
| "dev": "bun run --hot server/main.ts", | ||
| "build:server": "NODE_ENV=production bun build server/main.ts --target=bun --outfile=dist/server/main.js", | ||
| "build": "bun run build:server", | ||
| "publish": "cat app.json | deco registry publish -w /shared/deco -y", | ||
| "check": "tsc --noEmit", | ||
| "dev:tunnel": "deco link -p 3003 -- PORT=3003 bun run dev" | ||
| }, | ||
| "dependencies": { | ||
| "@decocms/bindings": "1.0.1-alpha.23", | ||
| "@decocms/runtime": "1.0.0-alpha.41", | ||
| "zod": "^3.24.3" | ||
| }, | ||
| "devDependencies": { | ||
| "@decocms/mcps-shared": "1.0.0", | ||
| "@modelcontextprotocol/sdk": "1.20.2", | ||
| "deco-cli": "^0.28.0", | ||
| "typescript": "^5.7.2" | ||
| }, | ||
| "engines": { | ||
| "node": ">=22.0.0" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /** | ||
| * API Documentation: https://developers.grain.com/ | ||
| */ | ||
| export const GRAIN_BASE_URL = "https://api.grain.com"; | ||
| export const GRAIN_LIST_RECORDINGS_ENDPOINT = "/_/public-api/recordings"; | ||
| export const GRAIN_RECORDING_ENDPOINT = "/_/public-api/recordings"; | ||
| export const GRAIN_TRANSCRIPT_ENDPOINT = | ||
| "/_/public-api/recordings/:id/transcript"; | ||
|
|
||
| // Webhook endpoints (API v2) | ||
| export const GRAIN_CREATE_WEBHOOK_ENDPOINT = "/_/public-api/v2/hooks/create"; | ||
| export const GRAIN_LIST_WEBHOOKS_ENDPOINT = "/_/public-api/v2/hooks"; | ||
| export const GRAIN_DELETE_WEBHOOK_ENDPOINT = "/_/public-api/v2/hooks"; | ||
|
|
||
| export const GRAIN_API_VERSION = "2025-10-31"; | ||
|
|
||
| export const DEFAULT_PAGE_SIZE = 50; | ||
| export const MAX_PAGE_SIZE = 100; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import type { Env } from "../types/env.ts"; | ||
|
|
||
| export const getGrainApiKey = (env: Env) => { | ||
| const authorization = env.MESH_REQUEST_CONTEXT.authorization; | ||
| if (!authorization) { | ||
| throw new Error( | ||
| "Authorization header is required. " + | ||
| "Please configure your Grain API key. " + | ||
| "You can get an API key from https://grain.com/settings/api", | ||
| ); | ||
| } | ||
| return authorization; | ||
| }; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.