Skip to main content
Glama

mcp-google-sheets

index.ts9.83 kB
import { AuthenticationType, httpClient, HttpMessageBody, HttpMethod, HttpRequest, HttpResponse, QueryParams, } from '@activepieces/pieces-common'; import { Property, OAuth2PropertyValue } from '@activepieces/pieces-framework'; import { isNil } from '@activepieces/shared'; export const githubCommon = { baseUrl: 'https://api.github.com', repositoryDropdown: Property.Dropdown<{ repo: string; owner: string }>({ displayName: 'Repository', refreshers: [], required: true, options: async ({ auth }) => { if (!auth) { return { disabled: true, options: [], placeholder: 'please authenticate first', }; } const authProp: OAuth2PropertyValue = auth as OAuth2PropertyValue; const repositories = await getUserRepo(authProp); return { disabled: false, options: repositories.map((repo) => { return { label: repo.owner.login + '/' + repo.name, value: { owner: repo.owner.login, repo: repo.name, }, }; }), }; }, }), milestoneDropdown: (required = false) => Property.Dropdown({ displayName: 'Milestone', description: 'The milestone to associate this issue with.', required, refreshers: ['repository'], options: async ({ auth, repository }) => { if (!auth || !repository) { return { disabled: true, options: [], placeholder: 'Please select a repository first', }; } const { owner, repo } = repository as RepositoryProp; const milestones = await githubPaginatedApiCall<{ number: number; title: string; }>({ accessToken: (auth as OAuth2PropertyValue).access_token, method: HttpMethod.GET, resourceUri: `/repos/${owner}/${repo}/milestones`, }); return { disabled: false, options: milestones.map((milestone) => { return { label: milestone.title, value: milestone.number, }; }), }; }, }), branchDropdown: (displayName: string, desc: string, required = true) => Property.Dropdown({ displayName, description: desc, required, refreshers: ['repository'], options: async ({ auth, repository }) => { if (!auth || !repository) { return { disabled: true, options: [], placeholder: 'Please select a repository first', }; } const { owner, repo } = repository as RepositoryProp; const branches = await githubPaginatedApiCall<{ name: string }>({ accessToken: (auth as OAuth2PropertyValue).access_token, method: HttpMethod.GET, resourceUri: `/repos/${owner}/${repo}/branches`, }); return { disabled: false, options: branches.map((branch) => { return { label: branch.name, value: branch.name, }; }), }; }, }), issueDropdown: (required = true) => Property.Dropdown({ displayName: 'Issue', description: 'The issue to select.', required, refreshers: ['repository'], options: async ({ auth, repository }) => { if (!auth || !repository) { return { disabled: true, options: [], placeholder: 'Please select a repository first', }; } const { owner, repo } = repository as RepositoryProp; // Fetch open issues from the repository const issues = await githubPaginatedApiCall<{ number: number; title: string; pull_request?: Record<string, any>; }>({ accessToken: (auth as OAuth2PropertyValue).access_token, method: HttpMethod.GET, resourceUri: `/repos/${owner}/${repo}/issues`, query: { state: 'open', // We will list open issues }, }); return { disabled: false, options: issues .filter((issue) => !issue.pull_request) .map((issue) => { return { label: `#${issue.number} - ${issue.title}`, value: issue.number, }; }), }; }, }), assigneeSingleDropdown: (required = false) => Property.Dropdown({ displayName: 'Assignee', description: 'Filter issues by a specific assignee.', required, refreshers: ['repository'], options: async ({ auth, repository }) => { if (!auth || !repository) { return { disabled: true, options: [], placeholder: 'please authenticate first and select repo', }; } const { owner, repo } = repository as RepositoryProp; const assignees = await getAssignee( auth as OAuth2PropertyValue, owner, repo ); return { disabled: false, options: assignees.map((assignee) => { return { label: assignee.login, value: assignee.login, }; }), }; }, }), assigneeDropDown: (required = false) => Property.MultiSelectDropdown({ displayName: 'Assignees', description: 'Assignees for the Issue', refreshers: ['repository'], required, options: async ({ auth, repository }) => { if (!auth || !repository) { return { disabled: true, options: [], placeholder: 'please authenticate first and select repo', }; } const authProp: OAuth2PropertyValue = auth as OAuth2PropertyValue; const { owner, repo } = repository as RepositoryProp; const assignees = await getAssignee(authProp, owner, repo); return { disabled: false, options: assignees.map((assignee) => { return { label: assignee.login, value: assignee.login, }; }), }; }, }), labelDropDown: (required = false) => Property.MultiSelectDropdown({ displayName: 'Labels', description: 'Labels for the Issue', refreshers: ['repository'], required, options: async ({ auth, repository }) => { if (!auth || !repository) { return { disabled: true, options: [], placeholder: 'please authenticate first and select repo', }; } const authProp: OAuth2PropertyValue = auth as OAuth2PropertyValue; const { owner, repo } = repository as RepositoryProp; const labels = await listIssueLabels(authProp, owner, repo); return { disabled: false, options: labels.map((label) => { return { label: label.name, value: label.name, }; }), }; }, }), }; async function getUserRepo(authProp: OAuth2PropertyValue) { const response = await githubPaginatedApiCall<{ id: number; name: string; owner: { login: string }; }>({ accessToken: authProp.access_token, method: HttpMethod.GET, resourceUri: '/user/repos', }); return response; } async function getAssignee( authProp: OAuth2PropertyValue, owner: string, repo: string ) { const response = await githubPaginatedApiCall<{ id: number; login: string }>({ accessToken: authProp.access_token, method: HttpMethod.GET, resourceUri: `/repos/${owner}/${repo}/assignees`, }); return response; } async function listIssueLabels( authProp: OAuth2PropertyValue, owner: string, repo: string ) { const response = await githubPaginatedApiCall<{ id: number; name: string }>({ accessToken: authProp.access_token, method: HttpMethod.GET, resourceUri: `/repos/${owner}/${repo}/labels`, }); return response; } export interface RepositoryProp { repo: string; owner: string; } export type RequestParams = Record< string, string | number | string[] | undefined >; export type GithubApiCallParams = { accessToken: string; method: HttpMethod; resourceUri: string; query?: RequestParams; body?: any; }; export async function githubApiCall<T extends HttpMessageBody>({ accessToken, method, resourceUri, query, body, }: GithubApiCallParams): Promise<HttpResponse<T>> { const baseUrl = 'https://api.github.com'; const qs: QueryParams = {}; if (query) { for (const [key, value] of Object.entries(query)) { if (value !== null && value !== undefined) { qs[key] = String(value); } } } const request: HttpRequest = { method, url: baseUrl + resourceUri, authentication: { type: AuthenticationType.BEARER_TOKEN, token: accessToken, }, queryParams: qs, body, }; const response = await httpClient.sendRequest<T>(request); return response; } export async function githubPaginatedApiCall<T extends HttpMessageBody>({ accessToken, method, resourceUri, query, body, }: GithubApiCallParams): Promise<T[]> { const qs = query ? query : {}; qs.page = 1; qs.per_page = 100; const resultData: T[] = []; let hasMoreItems = true; do { const response = await githubApiCall<T[]>({ accessToken, method, resourceUri, query: qs, body, }); qs.page = qs.page + 1; resultData.push(...response.body); const linkHeader = response.headers?.link; hasMoreItems = !isNil(linkHeader) && linkHeader.includes(`rel="next"`); } while (hasMoreItems); return resultData; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server