Gulpy
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Gulpyconnect my Notion account"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Gulpy
One login for all your AI plugins.
ChatGPT, Claude and Grok each have a list of plugins. You connect the same tools again in each one. Gulpy is one place for your connections. You add one address to each agent, a window opens, you tap Allow, and the agent has your tools.
"Plug", read from right to left, is "gulp". The mascot is a plug that eats tools.
The site | Your tools | A new agent asks |
|
|
|
The name is in one file: src/brand.ts. The folder and the key labels keep the first name, "connecty".
Run it
You need Bun 1.3 or later.
bun install
bun run devAddress | What it is |
Gulpy: the site, your tools, the approval window, the MCP server | |
Orbit, an agent to try Gulpy with. It knows the Gulpy address only. | |
Scout, a second agent |
Gulpy has no fake data. The tools are the real connectors in the list.
Do these steps:
Open Gulpy. Sign in with an email address. On this computer no mail goes out, so the page fills in the code.
Select + on a tool, for example Notion or Linear. You sign in at the provider.
Open Orbit. Select Connect with Gulpy. A window opens. Select Allow. Gulpy eats the tools and the window closes.
Ask Orbit a question about your tools.
Open Scout. Connect it. This is the one-tap flow.
Open Gulpy. You see the agents and each call. Remove the access of one agent.
Orbit and Scout think with the claude command of this computer, with your Claude
account. Each question uses a small part of your Claude plan. If the command is not
on the computer, the agents show a list of tools that you can run.
Related MCP server: nice
Add Gulpy to a real agent
Add a custom connector or MCP server with this address:
http://localhost:4000/mcpAn agent on your computer, such as Claude Code, can reach localhost:
claude mcp add --transport http gulpy http://localhost:4000/mcpChatGPT, Claude on the web and Grok call the connector from their servers. For
them, Gulpy must have a public https address. Set GULPY_BASE_URL to it.
Assistant | Steps |
Claude | Customize, then Connectors. Select "+", then "Add custom connector". Paste the address. |
ChatGPT | Settings, then Security and login. Turn on Developer mode. Create an app for a remote MCP server. |
Grok | grok.com/connectors. Select New Connector, then Custom. Paste the address. |
Real connectors
The list has 36 real connectors. On 2026-09-27 each address answered with its sign-in metadata.
Group | Count | What you must do |
Register automatically | 25 | Nothing. Select +. Notion, Linear, Atlassian, Stripe, Vercel, Supabase, Canva, Higgsfield and others. |
Need an app that you register at the provider | 7 | GitHub, Slack, HubSpot, Asana, Box, Render, Figma. The list shows them as "Soon". |
Use the API of the provider, with Gulpy tools | 4 | Gmail, Google Calendar, Outlook Email, Outlook Calendar |
Check the list against the real servers:
bun run scripts/check-catalog.ts # reads public metadata only
bun run scripts/check-catalog.ts --register # also registers Gulpy where the server permits itCredentials for the connectors that need an app. Put them in the environment, or in the macOS Keychain for development.
Connector | Environment | Redirect address to register |
GitHub, Slack, HubSpot, Asana, Box, Render, Figma |
|
|
Gmail, Google Calendar |
|
|
Outlook Email, Outlook Calendar |
|
|
security add-generic-password -a "$USER" -s gulpy-connector-github-client-id -w "<client id>" -U
security add-generic-password -a "$USER" -s gulpy-connector-github-client-secret -w "<client secret>" -UHow it works
Agent (Orbit, ChatGPT, Claude, Grok) Gulpy Connector (Notion)
| | |
| 1. POST /mcp with no token | |
|-------------------------------------------->| |
| 401, with the address of the metadata | |
| 2. reads the metadata, registers itself | |
|-------------------------------------------->| |
| 3. sends the user to /oauth/authorize | |
| the user selects connections and | (first time for a |
| taps Allow access | connector: the user |
| 4. code -> access token + refresh token | signs in at Notion) |
|<--------------------------------------------|------------------------------>|
| 5. tools/list, tools/call | tools/call with the token |
|-------------------------------------------->| of the user |
| |------------------------------>|Three objects carry the design:
A connection is one account at one connector. It belongs to the user. It holds the tokens, encrypted.
A grant gives one agent access to one connection, as Read only or Read and write. The user makes it on the approval page and can remove it.
A connector is an entry in the list. It is an MCP server that the provider operates, or a provider API for which Gulpy supplies the tools.
The agent never gets the token of a connector. Gulpy reads the grant on each call and then makes the call.
This follows the MCP authorization specification: OAuth 2.1 with PKCE, protected resource metadata (RFC 9728), server metadata (RFC 8414), dynamic client registration (RFC 7591), and client ID metadata documents. The specification forbids a server to pass on the token of the agent. It permits a proxy that has consent for each client. Gulpy is that proxy.
Link: connect from your own page
An app can also open Gulpy in a window from its own page, as Plaid Link does. Register the app at http://localhost:4000/developers.
// 1. On your server
const { link_token } = await post("/v1/link/token/create", {
client_id, secret, capabilities: ["email.read", "calendar.read"],
});<!-- 2. On your page. Call Gulpy.open directly in the click handler. -->
<script src="http://localhost:4000/link.js"></script>
<script>
button.onclick = () =>
Gulpy.open({
linkToken: () => fetch("/api/link-token", { method: "POST" }).then((r) => r.json()).then((d) => d.link_token),
onSuccess: ({ publicToken }) => fetch("/api/exchange", { method: "POST", body: JSON.stringify({ publicToken }) }),
});
</script>// 3. On your server
const { access_token } = await post("/v1/link/public_token/exchange", { client_id, secret, public_token });
const mail = await fetch("http://localhost:4000/v1/email/messages?q=invoice", {
headers: { authorization: `Bearer ${access_token}` },
});API for Link apps
All paths start with /v1. Errors have the shape { "error": { "code", "message" } }.
Method and path | Auth | What it does |
| client ID + secret | Makes a link token. It works for 30 minutes. |
| client ID + secret | Gives an access token for one user. |
| access token | Lists the accounts that the user shared. |
| access token | The app gives up its access to one account. |
| access token | |
| access token | Calendar |
| access token | A raw request to the provider API. Off by default. |
Error code | Status | Meaning |
| 403 | The user did not give this. |
| 409 | The provider cancelled the token. The user must reconnect. |
| 400 | The user shared two or more accounts. Send |
| 401 | The user removed the access, or the token is wrong. |
Settings
Variable | Default | Meaning |
|
| The public address of Gulpy |
| made and kept in the Keychain (development) | 32 bytes, base64. Encrypts the tokens. Necessary in production. |
|
| The SQLite file |
| not set | Sends sign-in codes by email. Necessary in production. |
| none | Provider ids for which |
Security model
Threat | Control |
The database is stolen | Tokens and client registrations are encrypted with AES-256-GCM. Each value is bound to its row. Secrets of apps, access tokens, refresh tokens and session IDs are stored as hashes only. |
An agent does more than the user approved | The agent never gets the token of a connector. Gulpy reads the grant on each call. Read access gives only the tools that say that they only read. |
A false agent asks for access | The approval page shows where the agent returns the user to, and says that the agent is not verified. Gulpy redirects only to a registered address. |
A copy of a refresh token | A refresh token works one time. A second use cancels all tokens of that sign-in. |
A stolen authorization code | PKCE with S256 is necessary. A code works one time, for 5 minutes. |
A client metadata address that points to the internal network | Gulpy refuses IP addresses and |
A page on a different site submits a form | Gulpy checks |
An attacker signs the victim in to the attacker's account | A sign-in code works only in the browser that asked for it. A provider callback works only in the session that started it. |
A hidden frame gets a click on Allow access | Pages forbid frames ( |
Two apps compare their users | Each Link app sees a different user ID for the same person. |
The user wants to know what happened | The dashboard shows each call. It records the tool and the result, not the content. |
Known gaps:
Tool descriptions come from the connector and go to the AI model. A bad connector can put instructions in them. Gulpy limits the length. It does not inspect the text.
The agents that register automatically are not verified. Gulpy has no list of known agents yet.
No rate limits. One server process only: the refresh lock is in memory.
Logos
Each connector and each agent shows the logo of its company. The images are in
src/assets/logos/. manifest.json in that folder has the source address of each one.
~/.local/py/bin/python scripts/fetch-logos.py # gets all logos again
~/.local/py/bin/python scripts/fetch-logos.py slack # gets oneAn agent gives its own name, so the name is not proof. The approval window shows the logo of Claude, ChatGPT, Grok or Cursor only if each return address of the agent is on the site of that company.
Project layout
src/
catalog.ts the list of connectors
logos.ts the logo images, and the rule for the logo of an agent
agents.ts Gulpy as an OAuth server for agents
upstream/ Gulpy as a client of an upstream MCP server
service.ts tools, mail, calendar and proxy operations
vault.ts token encryption and refresh
store.ts all SQL (SQLite), with migrations
link.ts Link: tokens, account choices, approval
oauth.ts sign-in at a provider that has its own API
providers/ google.ts, microsoft.ts
routes/ pages.tsx, info.tsx (support, security, privacy, terms), oauth.ts, mcp.ts, api.ts
views/ the pages
examples/
agent/ Orbit and Scout. They think with the `claude` command.
scripts/ dev.ts, check-catalog.ts, fetch-logos.py, make-social.py (the picture for link previews)
Dockerfile Gulpy for a host
test/ end-to-end tests. They use no network.
fixtures/ a mail provider and MCP connectors for the tests onlyTests
bun test # 104 tests
bun run typecheckStatus
Verified:
The full flow: 104 automated tests, and runs in a real browser (Chromium) with the pop-up window. The tests use a mail provider and connectors that exist for the tests only.
A real AI agent: Claude answered questions with tools that came through Gulpy.
The agent side, with the official MCP SDK as the agent: discovery, registration, sign-in, token refresh, tool calls.
The registration of Gulpy at 24 real connectors. Their sign-in pages show the name "Gulpy".
Gulpy in production mode with the real address setting (
https://gulpy.ai).
Not verified:
The container build from
Dockerfile.The sign-in of a user at a real connector, and a tool call with a real account. This needs your accounts. Select + on a tool to try it.
The Google and Microsoft adapters did not run against the real services.
ChatGPT, Claude and Grok as the agent. They need a public
httpsaddress.Mail to a real person. The
ResendMailersent one message to the test mailbox of Resend (HTTP 200).
Not built yet:
The 11 tools that show "Soon": Gmail, Google Calendar, Outlook Email, Outlook Calendar, GitHub, Slack, HubSpot, Asana, Box, Render, Figma. Each needs an app at the provider.
Skills and plugin packs. Gulpy has connectors only.
Connectors that use an API key and no OAuth, for example Exa and Firecrawl.
Passkeys for sign-in to Gulpy.
A search across the 830 connectors of the Claude directory.
Run your own Gulpy
Gulpy is one process with one SQLite file. You can run it on your own server and keep all your connections there.
Copy
.env.exampleto.env.Set
GULPY_BASE_URLto your publichttpsaddress.Set
GULPY_MASTER_KEYto 32 random bytes (openssl rand -base64 32). Keep a copy in a safe place. Without it, the stored tokens cannot be read.Set
RESEND_API_KEYandMAIL_FROM, so that the sign-in codes go out by email.Start it with
bun run start, or build theDockerfile.
Security
Report a security problem in private. Do not open a public issue. See SECURITY.md.
License
GNU Affero General Public License v3.0. You can use, change and run Gulpy for free. If you run a changed copy as a service for other people, you must publish your changes under the same license.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Connect any AI agent to 1,000+ apps and 27,000+ actions through one remote MCP server (OAuth).
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
- 0bridgeOAuthdev.0bridge
Every service you connect, one MCP endpoint for all your AI tools. Sign in once.
1
Related MCP Servers
FlicenseNot gradedqualityCmaintenanceSelf-hosted MCP gateway that connects Claude, ChatGPT, and other AI agents to 20+ enterprise tools (GitLab, Jira, Notion, Google Workspace, Slack, Grafana, …) with OAuth, audit logs, and zero data leaving your infrastructure-- AlicenseNot gradedqualityBmaintenanceProvides a secure MCP gateway for AI agents to access APIs without exposing raw credentials, with scoped access, audit logging, and OAuth support.MIT

SandBaseofficial
AlicenseNot gradedqualityBmaintenanceEnables AI assistants to discover and invoke 2,000+ models and APIs—including web search, social media, scraping, image/video generation, and audio—through a single local MCP bridge using OAuth, with no per-API keys.31 npm188Apache 2.0- AlicenseNot gradedqualityCmaintenanceProvides an OAuth-protected, scoped, and audited MCP server that lets AI assistants safely query business data through a fixed set of tools without direct database access.1MIT


