# Directory Structure
```
├── .env.example
├── .gitignore
├── .gitlab-ci.yml
├── Dockerfile
├── package-lock.json
├── package.json
├── README.MD
├── scripts
│ └── build.js
├── src
│ ├── api
│ │ ├── schemas.ts
│ │ ├── tldv-api.ts
│ │ └── types.ts
│ └── index.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
```
TLDV_API_KEY=dummy
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
node_modules
dist
DS_Store
.env
```
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
```yaml
stages:
- build
- release
- deploy
variables:
DOCKER_REGISTRY: $CI_REGISTRY
DOCKER_IMAGE: $CI_REGISTRY_IMAGE
release-version:
stage: release
image: node:22
script:
- git config --global user.email "${GIT_CI_EMAIL}"
- git config --global user.name "${GIT_CI_USER}"
- npm i standard-version --location=global
- npm run release -- --no-verify
- git remote set-url --push origin https://$GIT_CI_USER:[email protected]/$CI_PROJECT_PATH.git
- git push --follow-tags origin HEAD:$CI_COMMIT_REF_NAME
rules:
- if: $CI_COMMIT_BRANCH == "main" && $CI_COMMIT_TITLE !~ /^chore\(release\).*\ \[release\]$/
build:
stage: build
image: node:22
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
publish-npm:
stage: deploy
image: node:22
script:
- npm config set @tldx:registry=https://gitlab.com/api/v4/packages/npm/
- npm config set -- '//gitlab.com/api/v4/packages/npm/:_authToken'="${CI_JOB_TOKEN}"
- npm config set -- '//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken'="${CI_JOB_TOKEN}"
- npm ci
- npm run build
- npm publish
- echo "-- npm publish completed successfully"
rules:
- if: $CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v?[0-9]+\.[0-9]+\.[0-9]+$/
publish-docker:
stage: deploy
image: docker:latest
services:
- docker:dind
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build -t $DOCKER_IMAGE:$CI_COMMIT_TAG .
- docker tag $DOCKER_IMAGE:$CI_COMMIT_TAG $DOCKER_IMAGE:latest
- docker push $DOCKER_IMAGE:$CI_COMMIT_TAG
- docker push $DOCKER_IMAGE:latest
- echo "-- docker publish completed successfully"
rules:
- if: $CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /^v?[0-9]+\.[0-9]+\.[0-9]+$/
```
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
```markdown
# Official MCP Server for tl;dv API
🚀 **The First and Only MCP Server for Google Meet, Zoom, and Microsoft Teams Integration**
This project provides a Model Context Protocol (MCP) server enabling seamless interaction with the [tl;dv](https://tldv.io/) API. As the pioneering MCP solution for video conferencing platforms, it unlocks the power of tl;dv's meeting intelligence across Google Meet, Zoom, and Microsoft Teams through a standardized interface. This integration allows AI models and MCP clients to access, analyze, and derive insights from your meetings across all major platforms in one unified way.
## Features
* **List Meetings:** Retrieve meetings based on filters (query, date range, participation status, type) across all supported platforms.
* **Get Meeting Metadata:** Fetch detailed information for a specific meeting by ID, regardless of the platform it was hosted on.
* **Get Transcript:** Obtain the transcript for any meeting ID, with consistent formatting across all platforms.
* **Get Highlights:** Retrieve AI-generated highlights for meetings from any supported platform.
* **Import Meeting (Coming Soon):** Functionality to import meetings via URL from any supported platform.
## Prerequisites
* **tl;dv Account:** A Business or Enterprise tl;dv account is required.
* **tl;dv API Key:** You need an API key, which can be requested from your tl;dv settings: [https://tldv.io/app/settings/personal-settings/api-keys](https://tldv.io/app/settings/personal-settings/api-keys).
* **Node.js & npm (for Node installation):** If installing via Node.js, ensure Node.js and npm are installed.
* **Docker (for Docker installation):** If installing via Docker, ensure Docker is installed and running.
## Installation and Configuration
You can run this MCP server using either Docker or Node.js. Configure your MCP client (e.g., Claude Desktop, Cursor) to connect to the server.
### Using Docker
Go in the repo.
1. **Build the Docker image:**
```bash
docker build -t tldv-mcp-server .
```
2. **Configure your MCP Client:**
Update your MCP client's configuration file (e.g., `claude_desktop_config.json`). The exact location and format may vary depending on the client.
```json
{
"mcpServers": {
"tldv": {
"command": "docker",
"args": [
"run",
"--rm",
"--init",
"-e",
"TLDV_API_KEY=<your-tldv-api-key>",
"tldv-mcp-server"
],
}
}
}
```
Replace `<your-tldv-api-key>` with your actual tl;dv API key.
### Using Node.js
1. **Install dependencies:**
```bash
npm install
```
2. **Build the server:**
```bash
npm run build
```
This command creates a `dist` folder containing the compiled server code (`index.js`).
3. **Configure your MCP Client:**
Update your MCP client's configuration file.
```json
{
"mcpServers": {
"tldv": {
"command": "node",
"args": ["/absolute/path/to/tldv-mcp-server/dist/index.js"],
"env": {
"TLDV_API_KEY": "your_tldv_api_key"
}
}
}
}
```
Replace `/absolute/path/to/tldv-mcp-server/dist/index.js` with the correct absolute path to the built server file and `your_tldv_api_key` with your tl;dv API key.
*Refer to your specific MCP client's documentation for detailed setup instructions (e.g., [Claude Tools](https://modelcontextprotocol.io/quickstart/user)).*
*Disclaimer* Once you are updating this config file, you will need to kill your MCP client and restart it for the changes to be effective.
## Development
1. **Install dependencies:**
```bash
npm install
```
2. **Set up Environment Variables:**
Copy the example environment file:
```bash
cp .env.example .env
```
Edit the `.env` file and add your `TLDV_API_KEY`. Other variables can be configured as needed.
3. **Run in development mode:**
This command starts the server with auto-reloading on file changes:
```bash
npm run watch
```
4. **Update client for local development:**
Configure your MCP client to use the local development server path (typically `/path/to/your/project/dist/index.js`). Ensure the `TLDV_API_KEY` is accessible, either through the client's `env` configuration or loaded via the `.env` file by the server process.
5. **Reload your MCP Client**
Since you are running the watch command, it will recompiled a new version. Reloading your Client (e.g Claud Desktop App), your changes will be effective.
## Debugging
* **Console Logs:** Check the console output when running `npm run dev` for detailed logs. The server uses the `debug` library; you can control log levels via environment variables (e.g., `DEBUG=tldv-mcp:*`).
* **Node.js Debugger:** Utilize standard Node.js debugging tools (e.g., Chrome DevTools Inspector, VS Code debugger) by launching the server process with the appropriate flags (e.g., `node --inspect dist/index.js`).
* **MCP Client Logs:** Check the logs provided by your MCP client, which might show the requests sent and responses received from this server.
## Learn More
* [tl;dv Developer API Documentation](https://doc.tldv.io/)
* [Model Context Protocol (MCP) Specification](https://modelcontextprotocol.io/introduction)
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
"baseUrl": "./",
"sourceMap": false,
"inlineSources": false,
"removeComments": false,
"target": "ES2022",
"module": "NodeNext",
"declaration": true,
"outDir": "./dist",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"paths": {
"~/*": ["src/*"]
}
}
}
```
--------------------------------------------------------------------------------
/scripts/build.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
const { build } = require('esbuild');
async function bundle() {
try {
await build({
entryPoints: ['src/index.ts'],
bundle: true,
platform: 'node',
target: 'node22',
outfile: 'dist/index.js',
sourcemap: true,
minify: true,
format: 'cjs',
banner: {
js: '#!/usr/bin/env node',
},
// No external packages, include everything in the bundle
external: [],
});
console.log('Bundle complete! Output: dist/index.js');
} catch (error) {
console.error('Bundle failed:', error);
process.exit(1);
}
}
bundle();
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "tldv-mcp",
"version": "1.0.0",
"description": "TLDR API MCP Server",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"start": "node dist/index.js",
"dev": "ts-node-dev --respawn --transpile-only src/index.ts",
"build": "rm -rf dist && npm run bundle && chmod +x dist/*.js",
"bundle": "node scripts/build.js",
"prepare": "npm run build",
"watch": "tsc --watch",
"release": "standard-version -m \"chore(release): {{currentTag}} [release]\""
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.8.0",
"axios": "^1.8.4",
"dotenv": "^16.3.1",
"fastify": "^4.26.1",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/node": "^20.11.19",
"esbuild": "^0.25.2",
"esbuild-node-externals": "^1.18.0",
"ts-node-dev": "^2.0.0",
"typescript": "^5.3.3"
},
"volta": {
"node": "22.11.0"
}
}
```
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
```dockerfile
# Stage 1: Build the application
FROM node:22-slim AS builder
WORKDIR /app
# Copy package files and install dependencies
COPY package.json /app
COPY package-lock.json /app
COPY tsconfig.json /app
COPY src /app/src
# Use npm ci for cleaner installs, ensure package-lock.json exists
RUN npm install
# Build the TypeScript code
RUN npm run build
# Prune development dependencies
RUN npm prune --production
# Stage 2: Create the final production image
FROM node:22-slim
WORKDIR /app
# Create a non-root user
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
# Copy built code and production dependencies from the builder stage
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./
# Set ownership to the non-root user
RUN chown -R appuser:appgroup /app
# Switch to the non-root user
USER appuser
# Command to run the server
# The API key will be passed via environment variable at runtime
CMD ["node", "dist/index.js"]
```
--------------------------------------------------------------------------------
/src/api/types.ts:
--------------------------------------------------------------------------------
```typescript
export interface TldvConfig {
apiKey: string;
baseUrl?: string;
}
export interface TldvResponse<T> {
data: T;
error?: string;
}
export interface User {
name: string;
email: string;
}
export interface Template {
id: string;
label: string;
}
export interface Meeting {
id: string;
name: string;
happenedAt: string;
url: string;
organizer: User;
invitees: User[];
template: Template;
}
export interface Sentence {
speaker: string;
text: string;
startTime: number;
endTime: number;
}
export interface HighlightTopic {
title: string;
summary: string;
}
export interface Highlight {
text: string;
startTime: number;
source: 'manual' | 'auto';
topic: HighlightTopic;
}
export interface GetTranscriptResponse {
id: string;
meetingId: string;
data: Sentence[];
}
export interface GetHighlightsResponse {
meetingId: string;
data: Highlight[];
}
export interface ImportMeetingParams {
name: string;
url: string;
happenedAt?: string;
dryRun?: boolean;
}
export interface ImportMeetingResponse {
success: boolean;
jobId: string;
message: string;
}
export interface GetMeetingsParams {
query?: string;
page?: number;
limit?: number;
from?: string;
to?: string;
onlyParticipated?: boolean;
meetingType?: 'internal' | 'external';
}
export interface GetMeetingsResponse {
page: number;
pages: number;
total: number;
pageSize: number;
results: Meeting[];
}
export interface HealthResponse {
status: string;
}
export interface ValidationError {
property: string;
constraints: Record<string, string>;
}
export interface ValidationErrorResponse {
message: string;
error: {
message: string;
errors: ValidationError[];
}[];
}
export interface BasicErrorResponse {
name: string;
message: string;
}
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
import { GetMeetingsParamsSchema } from "./api/schemas";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { TldvApi } from "./api/tldv-api";
import dotenv from "dotenv";
import z from "zod";
dotenv.config();
async function main() {
console.info({ name: "Initializing TLDV API..." });
const tldvApi = new TldvApi({
apiKey: process.env.TLDV_API_KEY,
});
console.info({ name: "Starting MCP server..." });
const tools = {
"get-meeting-metadata": {
name: "get-meeting-metadata",
description: "Get a meeting by its ID. The meeting ID is a unique identifier for a meeting. It will return the meeting metadata, including the name, the date, the organizer, participants and more.",
inputSchema: z.object({ id: z.string() }),
},
"get-transcript": {
name: "get-transcript",
description: "Get transcript by meeting ID. The transcript is a list of messages exchanged between the participants in the meeting. It's time-stamped and contains the speaker and the message",
inputSchema: z.object({ meetingId: z.string() }),
},
"list-meetings": {
name: "list-meetings",
description: "List all meetings based on the filters provided. You can filter by date, status, and more. Those meetings are the sames you have access to in the TLDV app.",
inputSchema: GetMeetingsParamsSchema,
},
"get-highlights": {
name: "get-highlights",
description: "Allows you to get highlights from a meeting by providing a meeting ID.",
inputSchema: z.object({ meetingId: z.string() }),
},
};
const server = new McpServer({
name: "tldv-server",
version: "1.0.0",
}, {
capabilities: {
logging: {
level: "debug",
},
prompts: {},
tools: tools,
resources: {},
},
instructions: "You are a helpful assistant that can help with TLDV API requests.",
});
//Register tool handlers
server.tool(
tools["get-meeting-metadata"].name,
tools["get-meeting-metadata"].description,
tools["get-meeting-metadata"].inputSchema.shape,
async ({ id }) => {
const meeting = await tldvApi.getMeeting(id);
return {
content: [{ type: "text", text: JSON.stringify(meeting) }]
};
}
);
server.tool(
tools["get-transcript"].name,
tools["get-transcript"].description,
tools["get-transcript"].inputSchema.shape,
async ({ meetingId }) => {
const transcript = await tldvApi.getTranscript(meetingId);
return {
content: [{ type: "text", text: JSON.stringify(transcript) }]
};
}
);
server.tool(
tools["list-meetings"].name,
tools["list-meetings"].description,
tools["list-meetings"].inputSchema.shape,
async (input) => {
const meetings = await tldvApi.getMeetings(input);
return {
content: [{ type: "text", text: JSON.stringify(meetings) }]
};
}
);
server.tool(
tools["get-highlights"].name,
tools["get-highlights"].description,
tools["get-highlights"].inputSchema.shape,
async ({ meetingId }) => {
const highlights = await tldvApi.getHighlights(meetingId);
return {
content: [{ type: "text", text: JSON.stringify(highlights) }]
};
}
);
console.info({ message: "Initializing StdioServerTransport..." });
const transport = new StdioServerTransport();
console.info({ message: "Connecting to MCP server..." });
await server.connect(transport);
}
main().catch((error) => {
console.error({ message: "Fatal error in main():", error });
// process.exit(1);
});
```
--------------------------------------------------------------------------------
/src/api/schemas.ts:
--------------------------------------------------------------------------------
```typescript
import { z } from 'zod';
/**
* Configuration for the TLDR API client
*/
export const TldvConfigSchema = z.object({
apiKey: z.string().min(1, 'API key is required')
});
export type TldvConfig = z.infer<typeof TldvConfigSchema>;
/**
* Generic response wrapper for all API calls
*/
export const TldvResponseSchema = <T extends z.ZodType>(dataSchema: T) => dataSchema.nullable()
export type TldvResponse<T> = z.infer<ReturnType<typeof TldvResponseSchema<z.ZodType<T>>>>;
/**
* User information schema
*/
export const UserSchema = z.object({
name: z.string(),
email: z.string().email(),
});
export type User = z.infer<typeof UserSchema>;
/**
* Template information schema
*/
export const TemplateSchema = z.object({
id: z.string(),
label: z.string(),
});
export type Template = z.infer<typeof TemplateSchema>;
/**
* Meeting information schema
*/
export const MeetingSchema = z.object({
id: z.string(),
name: z.string(),
happenedAt: z.string().datetime(),
url: z.string().url(),
organizer: UserSchema,
invitees: z.array(UserSchema),
template: TemplateSchema,
});
export type Meeting = z.infer<typeof MeetingSchema>;
/**
* Sentence information schema for transcripts
*/
export const SentenceSchema = z.object({
speaker: z.string(),
text: z.string(),
startTime: z.number().int().nonnegative(),
endTime: z.number().int().nonnegative(),
});
export type Sentence = z.infer<typeof SentenceSchema>;
/**
* Highlight topic information schema
*/
export const HighlightTopicSchema = z.object({
title: z.string(),
summary: z.string(),
});
export type HighlightTopic = z.infer<typeof HighlightTopicSchema>;
/**
* Highlight information schema
*/
export const HighlightSchema = z.object({
text: z.string(),
startTime: z.number().int().nonnegative(),
source: z.enum(['manual', 'auto']),
topic: HighlightTopicSchema,
});
export type Highlight = z.infer<typeof HighlightSchema>;
/**
* Transcript response schema
*/
export const GetTranscriptResponseSchema = z.object({
id: z.string(),
meetingId: z.string(),
data: z.array(SentenceSchema),
});
export type GetTranscriptResponse = z.infer<typeof GetTranscriptResponseSchema>;
/**
* Highlights response schema
*/
export const GetHighlightsResponseSchema = z.object({
meetingId: z.string(),
data: z.array(HighlightSchema),
});
export type GetHighlightsResponse = z.infer<typeof GetHighlightsResponseSchema>;
/**
* Import meeting response schema
*/
export const ImportMeetingResponseSchema = z.object({
success: z.boolean(),
jobId: z.string(),
message: z.string(),
});
export type ImportMeetingResponse = z.infer<typeof ImportMeetingResponseSchema>;
/**
* Get meetings parameters schema
*/
export const GetMeetingsParamsSchema = z.object({
query: z.string().optional(), // search query
page: z.number().int().positive().optional(), // page number
limit: z.number().int().positive().optional().default(50), // number of results per page
from: z.string().datetime().optional(), // start date
to: z.string().datetime().optional(), // end date
onlyParticipated: z.boolean().optional(), // only return meetings where the user participated
// meeting type. internal is default.
// This is used to filter meetings by type. Type is determined by comparing the organizer's email with the invitees' emails.
// If the organizer's domain is different from at least one of the invitees' domains, the meeting is external.
// Otherwise, the meeting is internal.
meetingType: z.enum(['internal', 'external']).optional(),
});
export type GetMeetingsParams = z.infer<typeof GetMeetingsParamsSchema>;
/**
* Get meetings response schema
*/
export const GetMeetingsResponseSchema = z.object({
page: z.number().int().nonnegative(), // current page number
pages: z.number().int().positive(), // total number of pages
total: z.number().int().nonnegative(), // total number of results
pageSize: z.number().int().positive(), // number of results per page
results: z.array(MeetingSchema), // array of meetings
});
export type GetMeetingsResponse = z.infer<typeof GetMeetingsResponseSchema>;
/**
* Health check response schema
*/
export const HealthResponseSchema = z.object({
status: z.string(),
});
export type HealthResponse = z.infer<typeof HealthResponseSchema>;
/**
* Validation error schema
*/
export const ValidationErrorSchema = z.object({
property: z.string(),
constraints: z.record(z.string()),
});
export type ValidationError = z.infer<typeof ValidationErrorSchema>;
/**
* Validation error response schema
*/
export const ValidationErrorResponseSchema = z.object({
message: z.string(),
error: z.array(
z.object({
message: z.string(),
errors: z.array(ValidationErrorSchema),
})
),
});
export type ValidationErrorResponse = z.infer<typeof ValidationErrorResponseSchema>;
/**
* Basic error response schema
*/
export const BasicErrorResponseSchema = z.object({
name: z.string(),
message: z.string(),
});
export type BasicErrorResponse = z.infer<typeof BasicErrorResponseSchema>;
```
--------------------------------------------------------------------------------
/src/api/tldv-api.ts:
--------------------------------------------------------------------------------
```typescript
import {
GetHighlightsResponse,
GetMeetingsParams,
GetMeetingsParamsSchema,
GetMeetingsResponse,
GetTranscriptResponse,
HealthResponse,
Meeting,
TldvConfig,
TldvConfigSchema,
} from './schemas';
import { TldvResponse } from './types';
import axios from 'axios';
const BASE_URL = 'https://pasta.tldv.io/v1alpha1';
const MAX_RETRIES = 3;
const RETRY_DELAY = 1_000;
const MAX_RETRY_DELAY = 2_000;
/**
* TLDV API Client
*
* This class provides a type-safe interface to interact with the TLDV API.
* It handles authentication, request formatting, and response validation.
*
* @example
* ```typescript
* const api = new TldvApi({
* apiKey: 'your-api-key'
* });
*
* ```typescript
* const meeting = await tldvApi.getMeeting(id);
* ```
*/
export class TldvApi {
private apiKey: string;
private baseUrl: string;
private headers: any;
/**
* Creates a new instance of the TLDV API client
* @param config - Configuration object containing API key and optional base URL
* @throws {Error} If the configuration is invalid
*/
constructor(config: TldvConfig) {
const validatedConfig = TldvConfigSchema.parse(config);
this.apiKey = validatedConfig.apiKey;
this.baseUrl = BASE_URL;
this.headers = {
'x-api-key': this.apiKey,
'Content-Type': 'application/json',
};
}
/**
* Makes a request to the TLDV API
* @param endpoint - The API endpoint to call
* @param options - Request options including method, body, etc.
* @returns A promise that resolves to the validated API response
*/
private async request<T>(
endpoint: string,
options: RequestInit = {},
retryCount = 0,
maxRetries = MAX_RETRIES
): Promise<TldvResponse<T>> {
try {
const response = await axios(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
...this.headers,
},
});
if (response.status > 200) {
throw new Error(response.data.message || 'API request failed');
}
// Ensure the response is properly formatted
const responseData = response.data;
// If the response is already in the expected format, return it
if (responseData && typeof responseData === 'object' && 'data' in responseData) {
return responseData as TldvResponse<T>;
}
// Otherwise, wrap it in the expected format
return {
data: responseData as T,
error: undefined,
};
} catch (error) {
// Determine if we should retry based on the error
const shouldRetry =
retryCount < maxRetries &&
(
// Network errors
(error instanceof Error && error.message.includes('Network Error')) ||
// 5xx server errors
(axios.isAxiosError(error) && error.response && error.response.status >= 500) ||
// Rate limiting
(axios.isAxiosError(error) && error.response && error.response.status === 429)
);
if (shouldRetry) {
// Calculate exponential backoff delay: 2^retryCount * 1000ms (1s, 2s, 4s, etc.)
const delay = Math.min(RETRY_DELAY * 2 ** retryCount, MAX_RETRY_DELAY);
// Wait before retrying
await new Promise(resolve => setTimeout(resolve, delay));
// Retry the request
return this.request<T>(endpoint, options, retryCount + 1, maxRetries);
}
return {
data: null as T,
error: error instanceof Error ? error.message : 'Unknown error occurred',
};
}
}
/**
* Retrieves a meeting by its ID
*
* @param meetingId - The unique identifier of the meeting
* @returns A promise that resolves to the meeting details
*
* @example
* ```typescript
* const meeting = await api.getMeeting('meeting-123');
* ```
*/
async getMeeting(meetingId: string): Promise<TldvResponse<Meeting>> {
return this.request<Meeting>(`/meetings/${meetingId}`);
}
/**
* Retrieves a list of meetings with optional filtering
*
* @param params - Optional parameters for filtering and pagination
* @returns A promise that resolves to the paginated list of meetings
*
* @example
* ```typescript
* const meetings = await api.getMeetings({
* query: 'team sync',
* page: 1,
* limit: 10,
* from: '2024-01-01T00:00:00Z',
* to: '2024-12-31T23:59:59Z',
* onlyParticipated: true,
* meetingType: 'internal'
* });
* ```
*/
async getMeetings(params: GetMeetingsParams = {}): Promise<TldvResponse<GetMeetingsResponse>> {
const validatedParams = GetMeetingsParamsSchema.parse(params);
const queryParams = new URLSearchParams();
if (validatedParams.query) queryParams.append('query', validatedParams.query);
if (validatedParams.page) queryParams.append('page', validatedParams.page.toString());
if (validatedParams.limit) queryParams.append('limit', validatedParams.limit.toString());
if (validatedParams.from) queryParams.append('from', validatedParams.from);
if (validatedParams.to) queryParams.append('to', validatedParams.to);
if (validatedParams.onlyParticipated !== undefined) queryParams.append('onlyParticipated', validatedParams.onlyParticipated.toString());
if (validatedParams.meetingType) queryParams.append('meetingType', validatedParams.meetingType);
return this.request<GetMeetingsResponse>(`/meetings?${queryParams}`);
}
/**
* Retrieves the transcript for a specific meeting
*
* @param meetingId - The unique identifier of the meeting
* @returns A promise that resolves to the meeting transcript
*
* @example
* ```typescript
* const transcript = await api.getTranscript('meeting-123');
* ```
*/
async getTranscript(meetingId: string): Promise<TldvResponse<GetTranscriptResponse>> {
return this.request<GetTranscriptResponse>(`/meetings/${meetingId}/transcript`);
}
/**
* Retrieves the highlights for a specific meeting
*
* @param meetingId - The unique identifier of the meeting
* @returns A promise that resolves to the meeting highlights
*
* @example
* ```typescript
* const highlights = await api.getHighlights('meeting-123');
* ```
*/
async getHighlights(meetingId: string): Promise<TldvResponse<GetHighlightsResponse>> {
return this.request<GetHighlightsResponse>(`/meetings/${meetingId}/highlights`);
}
/**
* Checks the health status of the API
*
* @returns A promise that resolves to the health status
*
* @example
* ```typescript
* const health = await api.healthCheck();
* ```
*/
async healthCheck(): Promise<TldvResponse<HealthResponse>> {
return this.request<HealthResponse>('/health');
}
}
```