| 1 | import type { Provider } from "./integrations"; |
| 2 | |
| 3 | /** |
| 4 | * The connector catalog: every tool g1t connects to, or will, in one list. |
| 5 | * The workspace's Integrations page and your own Integrations settings are |
| 6 | * both drawn from it, so a new connector is added here, once. |
| 7 | * |
| 8 | * A connector is `available` when g1t can set it up today (its `href` is |
| 9 | * where), and `soon` while it is planned. `scopes` says who connects it: |
| 10 | * |
| 11 | * - `workspace`: an owner connects it once, for everyone in the workspace. |
| 12 | * - `personal`: each person connects their own account, and it follows them |
| 13 | * into every workspace they belong to (a calendar, a personal sign-in). |
| 14 | * |
| 15 | * A connector with both scopes can say something different for each, in |
| 16 | * `personal`: its own description, status, capabilities or setup page. |
| 17 | * `connectorView` resolves that into what one context shows. |
| 18 | * |
| 19 | * Paths in `href` are g1t's own pages. `:workspace` stands for the |
| 20 | * workspace's slug. |
| 21 | */ |
| 22 | |
| 23 | export type ConnectorScope = "workspace" | "personal"; |
| 24 | export type ConnectorStatus = "available" | "soon"; |
| 25 | |
| 26 | export type ConnectorCategory = |
| 27 | | "code" |
| 28 | | "issues" |
| 29 | | "chat" |
| 30 | | "calendar" |
| 31 | | "docs" |
| 32 | | "monitoring" |
| 33 | | "cloud" |
| 34 | | "ai" |
| 35 | | "data" |
| 36 | | "crm" |
| 37 | | "design" |
| 38 | | "security" |
| 39 | | "files"; |
| 40 | |
| 41 | /** What a connector lets g1t do, as the small tags on its card. */ |
| 42 | export type ConnectorCapability = |
| 43 | | "Agents can read" |
| 44 | | "Agents can act" |
| 45 | | "Opens issues" |
| 46 | | "Writes back" |
| 47 | | "Imports repositories" |
| 48 | | "Mirrors repositories" |
| 49 | | "Signs you in" |
| 50 | | "Sends events" |
| 51 | | "Alerts into chat" |
| 52 | | "Sets your status" |
| 53 | | "Finds a time" |
| 54 | | "Runs models" |
| 55 | | "Deploys" |
| 56 | | "Syncs people"; |
| 57 | |
| 58 | export type Connector = { |
| 59 | /** Stable and unique: used in links and requests. */ |
| 60 | id: string; |
| 61 | name: string; |
| 62 | category: ConnectorCategory; |
| 63 | /** One plain line of what it does in g1t, for a workspace (or for you, when it is only personal). */ |
| 64 | description: string; |
| 65 | scopes: ConnectorScope[]; |
| 66 | status: ConnectorStatus; |
| 67 | /** Where an available connector is set up, for each scope it has. */ |
| 68 | href?: Partial<Record<ConnectorScope, string>>; |
| 69 | capabilities?: ConnectorCapability[]; |
| 70 | /** The integration provider behind it, whose connections show it as connected. */ |
| 71 | provider?: Provider; |
| 72 | /** What differs when you connect it for yourself. */ |
| 73 | personal?: { description?: string; status?: ConnectorStatus; capabilities?: ConnectorCapability[] }; |
| 74 | /** More words search should find it by. */ |
| 75 | keywords?: string[]; |
| 76 | /** |
| 77 | * The remote MCP server behind it, when the tool publishes one: g1t |
| 78 | * connects to it (docs.g1t.sh/guides/customize/, "Connectors"), signs in |
| 79 | * the way it asks (`oauth`: the browser; `header`: a key an owner |
| 80 | * pastes; `none`), lists its tools, and gives them to agents. |
| 81 | */ |
| 82 | mcp?: { |
| 83 | url: string; |
| 84 | auth: "oauth" | "header" | "none"; |
| 85 | /** For `header`: the header the key goes in (Authorization when unset). */ |
| 86 | header?: string; |
| 87 | /** What to know before connecting: where the key comes from, or that signing in needs an app g1t doesn't have yet. */ |
| 88 | caveat?: string; |
| 89 | }; |
| 90 | }; |
| 91 | |
| 92 | /** A connector as one context (a workspace, or you) shows it. */ |
| 93 | export type ConnectorView = { |
| 94 | id: string; |
| 95 | name: string; |
| 96 | category: ConnectorCategory; |
| 97 | description: string; |
| 98 | status: ConnectorStatus; |
| 99 | href: string | null; |
| 100 | capabilities: ConnectorCapability[]; |
| 101 | provider: Provider | null; |
| 102 | keywords: string[]; |
| 103 | /** The other scope it can also be connected in. */ |
| 104 | alsoIn: ConnectorScope | null; |
| 105 | /** The MCP server behind it, when there is one. */ |
| 106 | mcp: Connector["mcp"] | null; |
| 107 | }; |
| 108 | |
| 109 | /** The categories, in the order the directory lists them. */ |
| 110 | export const CONNECTOR_CATEGORIES: { id: ConnectorCategory; title: string }[] = [ |
| 111 | { id: "code", title: "Code & CI" }, |
| 112 | { id: "issues", title: "Issues & projects" }, |
| 113 | { id: "chat", title: "Chat & meetings" }, |
| 114 | { id: "calendar", title: "Calendar & email" }, |
| 115 | { id: "docs", title: "Docs & knowledge" }, |
| 116 | { id: "monitoring", title: "Monitoring & incidents" }, |
| 117 | { id: "cloud", title: "Cloud & deploy" }, |
| 118 | { id: "ai", title: "AI models" }, |
| 119 | { id: "data", title: "Data & analytics" }, |
| 120 | { id: "crm", title: "CRM & support" }, |
| 121 | { id: "design", title: "Design" }, |
| 122 | { id: "security", title: "Security & identity" }, |
| 123 | { id: "files", title: "Files & storage" }, |
| 124 | ]; |
| 125 | |
| 126 | const W: ConnectorScope[] = ["workspace"]; |
| 127 | const P: ConnectorScope[] = ["personal"]; |
| 128 | const BOTH: ConnectorScope[] = ["workspace", "personal"]; |
| 129 | |
| 130 | /** A model provider: set up on the workspace's model providers page. */ |
| 131 | function model(provider: Provider, name: string, description: string, keywords: string[] = []): Connector { |
| 132 | return { |
| 133 | id: provider.replace(/_/g, "-"), |
| 134 | name, |
| 135 | category: "ai", |
| 136 | description, |
| 137 | scopes: W, |
| 138 | status: "available", |
| 139 | href: { workspace: `/:workspace/-/integrations/models?add=${provider}#add` }, |
| 140 | capabilities: ["Runs models"], |
| 141 | provider, |
| 142 | keywords: ["model", "llm", ...keywords], |
| 143 | }; |
| 144 | } |
| 145 | |
| 146 | /** Where an MCP-backed connector is connected: Customize's Connectors page, with the directory entry chosen. */ |
| 147 | export const MCP_CONNECT_PATH = "/:workspace/-/customize/connectors/new?directory="; |
| 148 | |
| 149 | /** |
| 150 | * A tool with a remote MCP server: available now, connected from Customize |
| 151 | * (an owner signs in or pastes a key), its tools then given to agents. |
| 152 | */ |
| 153 | function mcp( |
| 154 | id: string, |
| 155 | name: string, |
| 156 | category: ConnectorCategory, |
| 157 | description: string, |
| 158 | server: NonNullable<Connector["mcp"]>, |
| 159 | capabilities: ConnectorCapability[] = ["Agents can read", "Agents can act"], |
| 160 | keywords: string[] = [], |
| 161 | ): Connector { |
| 162 | return { id, name, category, description, scopes: W, status: "available", href: { workspace: `${MCP_CONNECT_PATH}${id}` }, capabilities, keywords: ["mcp", ...keywords], mcp: server }; |
| 163 | } |
| 164 | |
| 165 | /** A planned connector. */ |
| 166 | function soon( |
| 167 | id: string, |
| 168 | name: string, |
| 169 | category: ConnectorCategory, |
| 170 | scopes: ConnectorScope[], |
| 171 | description: string, |
| 172 | capabilities: ConnectorCapability[] = [], |
| 173 | personal?: Connector["personal"], |
| 174 | ): Connector { |
| 175 | return { id, name, category, description, scopes, status: "soon", capabilities, ...(personal ? { personal } : {}) }; |
| 176 | } |
| 177 | |
| 178 | export const CONNECTORS: Connector[] = [ |
| 179 | // Code & CI ------------------------------------------------------------- |
| 180 | { |
| 181 | id: "github", |
| 182 | name: "GitHub", |
| 183 | category: "code", |
| 184 | description: "Import repositories, or mirror them both ways while your team moves over.", |
| 185 | scopes: BOTH, |
| 186 | status: "available", |
| 187 | href: { workspace: "/new/github?workspace=:workspace", personal: "/settings/github" }, |
| 188 | capabilities: ["Imports repositories", "Mirrors repositories"], |
| 189 | personal: { |
| 190 | description: "Sign in with your GitHub account, and reach the repositories you can see there to import them.", |
| 191 | capabilities: ["Signs you in", "Imports repositories"], |
| 192 | }, |
| 193 | keywords: ["git", "import", "mirror", "sign in"], |
| 194 | }, |
| 195 | mcp("github-mcp", "GitHub (MCP)", "code", "Agents read and act on repositories, issues and pull requests on GitHub, through GitHub's MCP server.", { url: "https://api.githubcopilot.com/mcp/", auth: "header", header: "Authorization", caveat: "Paste a GitHub personal access token as Bearer <token>: GitHub's server takes one in place of a sign-in." }, ["Agents can read", "Agents can act"], ["issues", "pull requests"]), |
| 196 | { |
| 197 | id: "webhooks", |
| 198 | name: "Webhooks", |
| 199 | category: "code", |
| 200 | description: "Every repository's events, sent to your own addresses as they happen, signed.", |
| 201 | scopes: W, |
| 202 | status: "available", |
| 203 | href: { workspace: "/:workspace/-/webhooks" }, |
| 204 | capabilities: ["Sends events"], |
| 205 | keywords: ["http", "events", "outgoing"], |
| 206 | }, |
| 207 | soon("gitlab", "GitLab", "code", BOTH, "Import projects and keep them mirrored, merge requests included.", ["Imports repositories", "Mirrors repositories"], { |
| 208 | description: "Sign in with GitLab, and reach your own projects to import them.", |
| 209 | capabilities: ["Signs you in", "Imports repositories"], |
| 210 | }), |
| 211 | soon("bitbucket", "Bitbucket", "code", BOTH, "Import repositories and keep them mirrored while you move.", ["Imports repositories", "Mirrors repositories"], { |
| 212 | description: "Reach your own Bitbucket repositories to import them.", |
| 213 | capabilities: ["Imports repositories"], |
| 214 | }), |
| 215 | soon("circleci", "CircleCI", "code", W, "Pipeline results as checks on pull requests, which agents read when a build fails.", ["Agents can read"]), |
| 216 | soon("buildkite", "Buildkite", "code", W, "Build results as checks on pull requests, with the failing step for agents to fix.", ["Agents can read"]), |
| 217 | soon("docker-hub", "Docker Hub", "code", W, "Push images your workflows build, and pull private base images.", ["Deploys"]), |
| 218 | |
| 219 | // Issues & projects ----------------------------------------------------- |
| 220 | { |
| 221 | id: "linear", |
| 222 | name: "Linear", |
| 223 | category: "issues", |
| 224 | description: "Agents read ENG-42 when work mentions it; import issues, and they hear back when the work lands.", |
| 225 | scopes: BOTH, |
| 226 | status: "available", |
| 227 | href: { workspace: "/:workspace/-/integrations/trackers?add=linear#add" }, |
| 228 | capabilities: ["Agents can read", "Writes back"], |
| 229 | provider: "linear", |
| 230 | personal: { |
| 231 | description: "Issues assigned to you in Linear, in your g1t inbox beside everything else.", |
| 232 | status: "soon", |
| 233 | capabilities: ["Agents can read"], |
| 234 | }, |
| 235 | keywords: ["tracker", "tickets"], |
| 236 | }, |
| 237 | mcp("linear-mcp", "Linear (MCP)", "issues", "Agents search, create and update issues, projects and cycles in Linear, through Linear's MCP server.", { url: "https://mcp.linear.app/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["tracker", "issues"]), |
| 238 | { |
| 239 | id: "jira", |
| 240 | name: "Jira", |
| 241 | category: "issues", |
| 242 | description: "Agents read TECH-1234 when work mentions it; import tickets, and they hear back when the work lands.", |
| 243 | scopes: W, |
| 244 | status: "available", |
| 245 | href: { workspace: "/:workspace/-/integrations/trackers?add=jira#add" }, |
| 246 | capabilities: ["Agents can read", "Writes back"], |
| 247 | provider: "jira", |
| 248 | keywords: ["atlassian", "tracker", "tickets"], |
| 249 | }, |
| 250 | mcp("asana", "Asana", "issues", "Agents read, create and update tasks and projects in Asana, through Asana's MCP server.", { url: "https://mcp.asana.com/v2/mcp", auth: "oauth", caveat: "Asana signs in only apps registered with it, and g1t isn't one yet: signing in here fails until it is." }, ["Agents can read", "Agents can act"], ["tasks", "projects"]), |
| 251 | soon("shortcut", "Shortcut", "issues", W, "Stories agents read when work mentions them, updated when the work lands.", ["Agents can read", "Writes back"]), |
| 252 | soon("clickup", "ClickUp", "issues", W, "Tasks agents can read and import, kept in step with their pull requests.", ["Agents can read", "Writes back"]), |
| 253 | soon("trello", "Trello", "issues", W, "Cards become issues, and move along their board as the work does.", ["Opens issues", "Writes back"]), |
| 254 | |
| 255 | // Chat & meetings ------------------------------------------------------- |
| 256 | soon("slack", "Slack", "chat", BOTH, "Alerts and agent updates in the channels your team already reads, and agents to talk to there.", ["Alerts into chat", "Agents can act"], { |
| 257 | description: "Your status in g1t follows the one you set in Slack, and the other way round.", |
| 258 | capabilities: ["Sets your status"], |
| 259 | }), |
| 260 | soon("microsoft-teams", "Microsoft Teams", "chat", BOTH, "Alerts and agent updates posted to Teams channels, with agents to talk to there.", ["Alerts into chat", "Agents can act"], { |
| 261 | description: "Your status in g1t follows your Teams presence.", |
| 262 | capabilities: ["Sets your status"], |
| 263 | }), |
| 264 | soon("discord", "Discord", "chat", W, "Releases, alerts and agent updates posted to a Discord server.", ["Alerts into chat"]), |
| 265 | soon("zoom", "Zoom", "chat", BOTH, "Meeting notes and recordings agents can read when work refers to them.", ["Agents can read"], { |
| 266 | description: "Sets your status to On a call while you are in a Zoom meeting.", |
| 267 | capabilities: ["Sets your status"], |
| 268 | }), |
| 269 | soon("google-meet", "Google Meet", "chat", P, "Sets your status to On a call while you are in a meeting, and starts a call from any channel.", ["Sets your status"]), |
| 270 | |
| 271 | // Calendar & email ------------------------------------------------------ |
| 272 | soon("google-calendar", "Google Calendar", "calendar", P, "Sets your status to In a meeting while you are in one; agents can find a time that suits everyone.", ["Sets your status", "Finds a time"]), |
| 273 | soon("outlook-calendar", "Outlook Calendar", "calendar", P, "Sets your status to In a meeting while you are in one; agents can find a time that suits everyone.", ["Sets your status", "Finds a time"]), |
| 274 | soon("gmail", "Gmail", "calendar", P, "Forward a thread to an agent, or turn an email into an issue, from your own inbox.", ["Opens issues", "Agents can read"]), |
| 275 | soon("outlook-mail", "Outlook Mail", "calendar", P, "Forward a thread to an agent, or turn an email into an issue, from your own inbox.", ["Opens issues", "Agents can read"]), |
| 276 | |
| 277 | // Docs & knowledge ------------------------------------------------------ |
| 278 | mcp("notion", "Notion", "docs", "Agents search, read and write Notion pages and databases, through Notion's MCP server.", { url: "https://mcp.notion.com/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["pages", "wiki", "databases"]), |
| 279 | mcp("atlassian", "Atlassian (Jira and Confluence)", "docs", "Agents search and update Jira issues and Confluence pages, through Atlassian's MCP server.", { url: "https://mcp.atlassian.com/v1/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["jira", "confluence", "tickets", "wiki"]), |
| 280 | soon("google-docs", "Google Docs", "docs", BOTH, "Agents read the specs and plans linked from issues and chat.", ["Agents can read"], { |
| 281 | description: "Docs you share in chat open for agents as well as people.", |
| 282 | capabilities: ["Agents can read"], |
| 283 | }), |
| 284 | mcp("zapier", "Zapier", "data", "Agents run the actions you expose from Zapier, across thousands of apps, through Zapier's MCP server.", { url: "https://mcp.zapier.com/api/mcp/mcp", auth: "header", header: "Authorization", caveat: "Paste the token from your Zapier MCP settings as Bearer <token>." }, ["Agents can act"], ["automation", "apps"]), |
| 285 | soon("coda", "Coda", "docs", W, "Agents read the docs and tables linked from issues and chat.", ["Agents can read"]), |
| 286 | |
| 287 | // Monitoring & incidents ------------------------------------------------ |
| 288 | { |
| 289 | id: "sentry", |
| 290 | name: "Sentry", |
| 291 | category: "monitoring", |
| 292 | description: "New errors open issues with the stack trace, and resolve in Sentry when the fix merges.", |
| 293 | scopes: W, |
| 294 | status: "available", |
| 295 | href: { workspace: "/:workspace/-/integrations/alerts?add=sentry#add" }, |
| 296 | capabilities: ["Opens issues", "Agents can read", "Writes back"], |
| 297 | provider: "sentry", |
| 298 | keywords: ["errors", "alerts", "exceptions"], |
| 299 | }, |
| 300 | { |
| 301 | id: "datadog", |
| 302 | name: "Datadog", |
| 303 | category: "monitoring", |
| 304 | description: "Monitors that trigger open issues, and recoveries are noted on them.", |
| 305 | scopes: W, |
| 306 | status: "available", |
| 307 | href: { workspace: "/:workspace/-/integrations/alerts?add=datadog#add" }, |
| 308 | capabilities: ["Opens issues"], |
| 309 | provider: "datadog", |
| 310 | keywords: ["monitors", "alerts", "apm"], |
| 311 | }, |
| 312 | { |
| 313 | id: "alerts-webhook", |
| 314 | name: "Alerts webhook", |
| 315 | category: "monitoring", |
| 316 | description: "Anything that can send signed JSON opens issues: your own scripts, or any monitoring tool.", |
| 317 | scopes: W, |
| 318 | status: "available", |
| 319 | href: { workspace: "/:workspace/-/integrations/alerts?add=webhook#add" }, |
| 320 | capabilities: ["Opens issues"], |
| 321 | provider: "webhook", |
| 322 | keywords: ["incoming", "http", "alerts", "pagerduty", "grafana"], |
| 323 | }, |
| 324 | mcp("sentry-mcp", "Sentry (MCP)", "monitoring", "Agents search issues, read stack traces and look up errors in Sentry, through Sentry's MCP server.", { url: "https://mcp.sentry.dev/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["errors", "issues"]), |
| 325 | soon("pagerduty", "PagerDuty", "monitoring", BOTH, "Incidents open issues an agent can start on, and resolve when the fix lands.", ["Opens issues", "Writes back"], { |
| 326 | description: "Sets your status to On call while you are on call.", |
| 327 | capabilities: ["Sets your status"], |
| 328 | }), |
| 329 | soon("opsgenie", "Opsgenie", "monitoring", W, "Alerts open issues, and close when the fix lands.", ["Opens issues", "Writes back"]), |
| 330 | soon("incident-io", "incident.io", "monitoring", W, "Incidents get a channel in g1t, with agents to dig through what changed.", ["Opens issues", "Alerts into chat"]), |
| 331 | soon("grafana", "Grafana", "monitoring", W, "Alert rules open issues, and agents read the dashboards they link to.", ["Opens issues", "Agents can read"]), |
| 332 | soon("new-relic", "New Relic", "monitoring", W, "Alerts open issues, with the traces agents need to find the cause.", ["Opens issues", "Agents can read"]), |
| 333 | soon("honeycomb", "Honeycomb", "monitoring", W, "Triggers open issues, and agents query traces while they work.", ["Opens issues", "Agents can read"]), |
| 334 | soon("better-stack", "Better Stack", "monitoring", W, "Uptime incidents and log alerts open issues.", ["Opens issues"]), |
| 335 | |
| 336 | // Cloud & deploy -------------------------------------------------------- |
| 337 | mcp("cloudflare", "Cloudflare", "cloud", "Agents read your Cloudflare account's Workers, storage and settings, and look things up in its docs, through Cloudflare's MCP servers.", { url: "https://bindings.mcp.cloudflare.com/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["workers", "r2", "d1", "dns"]), |
| 338 | mcp("cloudflare-docs", "Cloudflare docs", "docs", "Agents search Cloudflare's documentation while they work.", { url: "https://docs.mcp.cloudflare.com/mcp", auth: "none" }, ["Agents can read"], ["documentation"]), |
| 339 | soon("aws", "Amazon Web Services", "cloud", W, "Workflows and deployments reach AWS with short-lived credentials, no stored keys.", ["Deploys"]), |
| 340 | soon("google-cloud", "Google Cloud", "cloud", W, "Workflows and deployments reach Google Cloud with short-lived credentials.", ["Deploys"]), |
| 341 | soon("azure", "Microsoft Azure", "cloud", W, "Workflows and deployments reach Azure with short-lived credentials.", ["Deploys"]), |
| 342 | mcp("vercel", "Vercel", "cloud", "Agents read your Vercel projects, deployments and logs, through Vercel's MCP server.", { url: "https://mcp.vercel.com", auth: "oauth" }, ["Agents can read", "Agents can act"], ["deployments", "previews"]), |
| 343 | soon("netlify", "Netlify", "cloud", W, "Deploy previews as checks on pull requests.", ["Deploys", "Agents can read"]), |
| 344 | soon("fly-io", "Fly.io", "cloud", W, "Deploy apps from workflows, and roll back from the deployment's page.", ["Deploys"]), |
| 345 | soon("kubernetes", "Kubernetes", "cloud", W, "Roll out to your own clusters from workflows, with each rollout's status on g1t.", ["Deploys"]), |
| 346 | |
| 347 | // AI models ------------------------------------------------------------- |
| 348 | model("anthropic", "Anthropic", "Claude models on your own Anthropic account, billed there.", ["claude"]), |
| 349 | model("openai", "OpenAI", "GPT models on your own OpenAI account, billed there.", ["gpt"]), |
| 350 | model("gemini", "Google Gemini", "Gemini models on your own Google AI account, billed there.", ["google"]), |
| 351 | model("xai", "xAI", "Grok models on your own xAI account, billed there.", ["grok"]), |
| 352 | model("mistral", "Mistral", "Mistral models on your own account, billed there."), |
| 353 | model("deepseek", "DeepSeek", "DeepSeek models on your own account, billed there."), |
| 354 | model("azure_openai", "Azure OpenAI", "Your Azure OpenAI deployments, in your own subscription.", ["microsoft"]), |
| 355 | model("openrouter", "OpenRouter", "Many labs' models through one OpenRouter key."), |
| 356 | model("groq", "Groq", "Fast open models on your own Groq account."), |
| 357 | model("together", "Together AI", "Open models on your own Together AI account."), |
| 358 | model("fireworks", "Fireworks AI", "Open models on your own Fireworks AI account."), |
| 359 | model("cerebras", "Cerebras", "Fast open models on your own Cerebras account."), |
| 360 | model("anthropic_endpoint", "Anthropic-compatible endpoint", "Any server that speaks the Anthropic API, such as your own gateway.", ["self-hosted", "proxy"]), |
| 361 | model("openai_endpoint", "OpenAI-compatible endpoint", "Any server that speaks the OpenAI API, such as a model you host yourself.", ["self-hosted", "proxy", "ollama", "vllm"]), |
| 362 | { |
| 363 | id: "ai-gateway", |
| 364 | name: "AI Gateway", |
| 365 | category: "ai", |
| 366 | description: "Your own code's model requests through g1t, with the workspace's access tokens, logged and costed.", |
| 367 | scopes: W, |
| 368 | status: "available", |
| 369 | href: { workspace: "/:workspace/-/gateway" }, |
| 370 | capabilities: ["Runs models"], |
| 371 | keywords: ["proxy", "api", "tokens"], |
| 372 | }, |
| 373 | { |
| 374 | id: "mcp", |
| 375 | name: "MCP clients", |
| 376 | category: "ai", |
| 377 | description: "Your own agent, connected to g1t's MCP server, works in g1t as you.", |
| 378 | scopes: P, |
| 379 | status: "available", |
| 380 | href: { personal: "/settings/applications" }, |
| 381 | capabilities: ["Agents can act"], |
| 382 | keywords: ["model context protocol", "agent", "applications", "oauth"], |
| 383 | }, |
| 384 | soon("amazon-bedrock", "Amazon Bedrock", "ai", W, "Models in your own AWS account, billed there.", ["Runs models"]), |
| 385 | soon("vertex-ai", "Google Vertex AI", "ai", W, "Models in your own Google Cloud project, billed there.", ["Runs models"]), |
| 386 | mcp("hugging-face", "Hugging Face", "ai", "Agents search models, datasets, papers and Spaces on the Hub, through Hugging Face's MCP server.", { url: "https://huggingface.co/mcp", auth: "oauth" }, ["Agents can read"], ["models", "datasets", "hub"]), |
| 387 | mcp("context7", "Context7", "docs", "Agents read current documentation for the libraries a codebase uses, through Context7's MCP server.", { url: "https://mcp.context7.com/mcp", auth: "none" }, ["Agents can read"], ["documentation", "libraries"]), |
| 388 | mcp("microsoft-learn", "Microsoft Learn", "docs", "Agents search Microsoft's documentation for Azure, .NET and Windows, through Microsoft Learn's MCP server.", { url: "https://learn.microsoft.com/api/mcp", auth: "none" }, ["Agents can read"], ["azure", "dotnet", "documentation"]), |
| 389 | mcp("deepwiki", "DeepWiki", "docs", "Agents read generated documentation for public repositories, through DeepWiki's MCP server.", { url: "https://mcp.deepwiki.com/mcp", auth: "none" }, ["Agents can read"], ["repositories", "documentation"]), |
| 390 | |
| 391 | // Data & analytics ------------------------------------------------------ |
| 392 | soon("postgresql", "PostgreSQL", "data", W, "Agents read your schema, and run read-only queries while they investigate.", ["Agents can read"]), |
| 393 | soon("snowflake", "Snowflake", "data", W, "Agents answer questions from your warehouse with read-only queries.", ["Agents can read"]), |
| 394 | soon("bigquery", "BigQuery", "data", W, "Agents answer questions from your datasets with read-only queries.", ["Agents can read"]), |
| 395 | mcp("posthog", "PostHog", "data", "Agents read product analytics, feature flags and errors in PostHog, through PostHog's MCP server.", { url: "https://mcp.posthog.com/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["analytics", "feature flags"]), |
| 396 | mcp("supabase", "Supabase", "data", "Agents read your Supabase projects, schemas and logs, and run queries, through Supabase's MCP server.", { url: "https://mcp.supabase.com/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["postgres", "database"]), |
| 397 | mcp("neon", "Neon", "data", "Agents read and manage Neon Postgres projects and branches, through Neon's MCP server.", { url: "https://mcp.neon.tech/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["postgres", "database"]), |
| 398 | soon("amplitude", "Amplitude", "data", W, "Agents read the charts that work refers to.", ["Agents can read"]), |
| 399 | soon("segment", "Segment", "data", W, "Agents read your tracking plan, and check new events against it.", ["Agents can read"]), |
| 400 | |
| 401 | // CRM & support --------------------------------------------------------- |
| 402 | soon("zendesk", "Zendesk", "crm", W, "Turn a ticket into an issue, and tell the customer when the fix ships.", ["Opens issues", "Writes back"]), |
| 403 | mcp("intercom", "Intercom", "crm", "Agents search conversations, contacts and companies in Intercom, through Intercom's MCP server.", { url: "https://mcp.intercom.com/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["support", "conversations", "customers"]), |
| 404 | mcp("hubspot", "HubSpot", "crm", "Agents read contacts, companies and deals in HubSpot, through HubSpot's MCP server.", { url: "https://mcp.hubspot.com/anthropic", auth: "oauth", caveat: "HubSpot signs in only apps registered with it, and g1t isn't one yet: signing in here fails until it is." }, ["Agents can read", "Agents can act"], ["crm", "contacts", "deals"]), |
| 405 | soon("salesforce", "Salesforce", "crm", W, "Agents read the account and case behind a request.", ["Agents can read"]), |
| 406 | mcp("stripe", "Stripe", "crm", "Agents read customers, payments and subscriptions, and look things up in Stripe's docs, through Stripe's MCP server.", { url: "https://mcp.stripe.com", auth: "oauth" }, ["Agents can read", "Agents can act"], ["payments", "billing", "customers"]), |
| 407 | mcp("paypal", "PayPal", "crm", "Agents read and manage orders, invoices and subscriptions, through PayPal's MCP server.", { url: "https://mcp.paypal.com/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["payments", "invoices"]), |
| 408 | |
| 409 | // Design ---------------------------------------------------------------- |
| 410 | mcp("figma", "Figma", "design", "Agents read designs, components and variables from your Figma files, and build to them, through Figma's MCP server.", { url: "https://mcp.figma.com/mcp", auth: "oauth" }, ["Agents can read"], ["design", "frames", "components"]), |
| 411 | mcp("canva", "Canva", "design", "Agents search, create and export Canva designs, through Canva's MCP server.", { url: "https://mcp.canva.com/mcp", auth: "oauth" }, ["Agents can read", "Agents can act"], ["design", "slides"]), |
| 412 | soon("miro", "Miro", "design", W, "Agents read the boards linked from issues and chat.", ["Agents can read"]), |
| 413 | soon("storybook", "Storybook", "design", W, "Each pull request's stories as a check, with what changed.", ["Agents can read"]), |
| 414 | |
| 415 | // Security & identity --------------------------------------------------- |
| 416 | soon("okta", "Okta", "security", W, "Single sign-on, and people added and removed with your directory.", ["Signs you in", "Syncs people"]), |
| 417 | soon("entra-id", "Microsoft Entra ID", "security", W, "Single sign-on, and people added and removed with your directory.", ["Signs you in", "Syncs people"]), |
| 418 | soon("google-workspace", "Google Workspace", "security", BOTH, "Single sign-on, and people added and removed with your directory.", ["Signs you in", "Syncs people"], { |
| 419 | description: "Sign in to g1t with your Google account.", |
| 420 | capabilities: ["Signs you in"], |
| 421 | }), |
| 422 | soon("1password", "1Password", "security", W, "Secrets from a vault, read by workflows and deployments when they run.", ["Deploys"]), |
| 423 | soon("snyk", "Snyk", "security", W, "Findings open issues, and an agent opens the fix.", ["Opens issues"]), |
| 424 | |
| 425 | // Files & storage ------------------------------------------------------- |
| 426 | soon("google-drive", "Google Drive", "files", BOTH, "Agents read the files linked from issues and chat.", ["Agents can read"], { |
| 427 | description: "Attach files from your Drive in chat, without downloading them first.", |
| 428 | capabilities: ["Agents can read"], |
| 429 | }), |
| 430 | soon("dropbox", "Dropbox", "files", BOTH, "Agents read the files linked from issues and chat.", ["Agents can read"], { |
| 431 | description: "Attach files from your Dropbox in chat.", |
| 432 | capabilities: ["Agents can read"], |
| 433 | }), |
| 434 | soon("onedrive", "OneDrive and SharePoint", "files", BOTH, "Agents read the files linked from issues and chat.", ["Agents can read"], { |
| 435 | description: "Attach files from your OneDrive in chat.", |
| 436 | capabilities: ["Agents can read"], |
| 437 | }), |
| 438 | soon("box", "Box", "files", W, "Agents read the files linked from issues and chat.", ["Agents can read"]), |
| 439 | ]; |
| 440 | |
| 441 | /** The connector by its id. */ |
| 442 | export function connectorById(id: string): Connector | undefined { |
| 443 | return CONNECTORS.find((connector) => connector.id === id); |
| 444 | } |
| 445 | |
| 446 | /** A connector as `scope` shows it, or null when it cannot be connected there. */ |
| 447 | export function connectorView(connector: Connector, scope: ConnectorScope): ConnectorView | null { |
| 448 | if (!connector.scopes.includes(scope)) return null; |
| 449 | const own = scope === "personal" ? connector.personal : undefined; |
| 450 | const status = own?.status ?? connector.status; |
| 451 | const other: ConnectorScope = scope === "workspace" ? "personal" : "workspace"; |
| 452 | return { |
| 453 | id: connector.id, |
| 454 | name: connector.name, |
| 455 | category: connector.category, |
| 456 | description: own?.description ?? connector.description, |
| 457 | status, |
| 458 | href: status === "available" ? (connector.href?.[scope] ?? null) : null, |
| 459 | capabilities: own?.capabilities ?? connector.capabilities ?? [], |
| 460 | provider: connector.provider ?? null, |
| 461 | keywords: connector.keywords ?? [], |
| 462 | alsoIn: connector.scopes.includes(other) ? other : null, |
| 463 | mcp: connector.mcp ?? null, |
| 464 | }; |
| 465 | } |
| 466 | |
| 467 | /** Every connector `scope` can show, in catalog order. */ |
| 468 | export function connectorsFor(scope: ConnectorScope): ConnectorView[] { |
| 469 | return CONNECTORS.map((connector) => connectorView(connector, scope)).filter((view): view is ConnectorView => view != null); |
| 470 | } |
| 471 | |
| 472 | /** A setup path with its `:workspace` filled in. */ |
| 473 | export function connectorPath(path: string, workspace: string): string { |
| 474 | return path.replace(/:workspace\b/g, encodeURIComponent(workspace)); |
| 475 | } |