Context teleportation protocol and shared memory bus for AI assistants.
PORTAL
Context teleportation protocol and shared memory bus for AI assistants.
PORTAL is a local Model Context Protocol (MCP) server that lets different AI assistants running on the same machine work together. It currently supports Claude Desktop, Codex, and Gemini (Antigravity IDE).
It provides two things:
- Cross-agent chat. One assistant can send a message to another assistant and receive its reply, directly from the chat session, without copy-paste.
- Shared context. A common store for the project objective, progress checklist, design decisions, and local file contents, synced across workspaces.
Architecture
+--------------------------------------------------------+
| Your AI clients |
| +----------------+ +--------------+ +------------+ |
| | Claude Desktop | | Codex | | Gemini IDE | |
| +-------+--------+ +------+-------+ +------+-----+ |
+-----------|-----------------|----------------|---------+
| MCP | MCP | MCP / gRPC
v v v
+----------------------------------------------+
| Deno MCP server (mcp_portal.ts) |
+----------------------|-----------------------+
v
+------------------------------------------------+
| SQLite database (portal.db) |
| (shared state, decisions, messages) |
+----------------------^-------------------------+
| read / write
+----------------------v-------------------------+
| Rust bridge (mcp-portal-bridge.exe) |
| - watches the message queues |
| - runs headless Claude/Codex CLI calls |
| - injects messages into active Gemini chats |
+------------------------------------------------+
Components:
- SQLite database (
portal.db): the source of truth. Stores portal metadata, shared file contents, the design decision log, and cross-agent message queues. - Deno MCP server (
mcp_portal.ts): implements the Model Context Protocol. Exposes context, decisions, and shared files as MCP resources, and control operations as MCP tools. - Rust bridge (
mcp-portal-bridge): a persistent Windows background process that watches the message queues and does two jobs. When Gemini asks a question, it runs a headless CLI invocation of Claude (claude -p) or Codex (codex exec) and writes the reply back to the database. When Claude or Codex replies, it reads the active Gemini IDE port and CSRF token from the running process list and uses the internal gRPC API (agentapi) to deliver the message into the active chat window.
Features
- Context teleportation: pull goals, progress, and current blockers into any new chat.
- Design decision log: a shared record of architectural choices to avoid regressions.
- File sharing: reference and load local file contents across assistants.
- Cross-agent chat: ask a question to another assistant and get the answer back.
- Connection reuse: connections are bound to client process PIDs. Restart an IDE or Claude Desktop and the session resumes.
Requirements
-
Deno. Install with WinGet:
winget install DenoLand.Deno -
Rust (
cargo), to build the bridge daemon.
Setup
1. Set the home directory
Set MCP_PORTAL_HOME to the directory where this repository lives:
setx MCP_PORTAL_HOME "C:\path\to\mcp-portal"
2. Register the MCP server with Claude Desktop
Add the server to %APPDATA%\Claude\claude_desktop_config.json:
{
"mcpServers": {
"mcp-portal": {
"command": "powershell.exe",
"args": [
"-NoProfile",
"-Command",
"$portal = $env:MCP_PORTAL_HOME; if (-not $portal) { throw 'Set MCP_PORTAL_HOME to the mcp-portal directory.' }; deno run --no-check --allow-read --allow-write --allow-env --allow-run --allow-ffi (Join-Path $portal 'mcp_portal.ts')"
]
}
}
}
Optional path overrides:
| Variable | Default |
| :--- | :--- |
| MCP_PORTAL_DB_DIR | %USERPROFILE%\.gemini\antigravity\scratch\mcp-portal |
| ANTIGRAVITY_BRAIN_DIR | %USERPROFILE%\.gemini\antigravity\brain |
| ANTIGRAVITY_LS_EXE | %LOCALAPPDATA%\Programs\antigravity\resources\bin\language_server.exe |
| CLAUDE_CODE_DIR | %APPDATA%\Claude\claude-code |
| CODEX_EXE | codex from PATH |
3. Build and run the Rust bridge
cd mcp-portal-bridge
cargo build --release
.\target\release\mcp-portal-bridge.exe
To run the bridge at login, put a shortcut to mcp-portal-bridge.exe in the
Windows Startup folder (%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup).
Prebuilt mcp-portal-bridge.exe binaries are attached to each tagged release on
the Releases page.
MCP tools
| Tool | Parameters | Description |
| :--- | :--- | :--- |
| portal_create | name (optional) | Creates a new portal session and returns a token (portal://TOKEN). |
| portal_connect | portalUrl (required) | Joins an existing portal by token or URL. |
| portal_update_context | objective, summary, todo, blockers | Updates the shared checklist and goals. |
| portal_add_decision | decision, rationale | Appends an architectural choice to the decision log. |
| portal_share_file | filePath, content (optional) | Shares a local file. Reads from disk if content is omitted. |
| portal_sync | lastSeenMsgId (optional) | Pulls the latest context, files, decisions, and messages. |
| portal_ask | content (required), timeoutMs | Asks another assistant a question and blocks until a reply arrives. |
| portal_send_message | content, replyToId (optional) | Posts a message to the shared channel. |
| portal_status | none | Shows the current PID, client name, and active portal URL. |
| gemini_list_conversations | none | Lists local Gemini IDE conversations and activity times. |
| gemini_create_conversation | prompt (required) | Starts a new chat in the Gemini IDE. |
| gemini_select_conversation | conversationId | Pins a Gemini chat as the target for portal messages. |
| gemini_get_selected_conversation | none | Returns the pinned Gemini conversation ID. |
| gemini_select_conversation (reset) | empty string or null | Reverts to the most recently active conversation on disk. |
Agent support
The integration level depends on whether the target agent exposes a local API that allows message delivery.
Gemini / Antigravity
Gemini IDE exposes an internal gRPC API (agentapi) on localhost. PORTAL uses it
to deliver messages into the active running chat window. This allows:
- Message delivery into the active conversation in real time.
- Messages land in a real Gemini conversation with history, memory, and tool access.
- Conversation control: create, list, and pin conversations from another assistant.
Claude
Claude Desktop does not expose a local injection API, and its GUI cannot be
driven remotely. The DevTools/CDP route is blocked: the app holds a global
single-instance lock and strips --remote-debugging-port during its update
self-relaunch. PORTAL therefore does not inject into the Claude Desktop window.
Instead, the bridge answers through the Claude Code CLI with a persistent
session. Each portal gets a deterministic session UUID derived from the portal
ID, so the responder uses --resume on every turn and falls back to
--session-id to create the session on first use:
- Persistent context: the answering Claude keeps the full conversation history
across portal exchanges, unlike a bare
claude -p. The session ID is stable per portal, so context survives bridge restarts. - No UI footprint: replies are generated headlessly and written back to the database. The Desktop window is not involved.
- Text-only responder: launched with
--tools ""(tools disabled) and the prompt piped through stdin.
Codex
Codex is queried as a stateless fallback through codex exec --ephemeral. It
runs only when Claude is unavailable (quota or auth).
Usage
1. Create a portal
In your main workspace (for example, Claude Desktop):
Create a PORTAL for our project.
Claude calls portal_create and returns a token, for example portal://GHMLRK.
2. Connect the second assistant
In the secondary environment (for example, Gemini IDE):
Join the portal portal://GHMLRK
Gemini calls portal_connect and loads the active context, goals, and shared
files.
3. Ask another agent
While working in Gemini:
Ask Claude whether we should implement this as a struct or a trait.
Gemini calls portal_ask. The bridge runs the Claude CLI in the background,
fetches the response, and delivers it to the Gemini chat panel.
4. Manage Gemini conversations
List conversations:
List my Gemini conversations.
Calls gemini_list_conversations and returns conversation IDs and last activity
times.
Create a new conversation and pin it as the target:
Create a new Gemini conversation about our Rust migration plan.
Calls gemini_create_conversation. The new conversation is pinned, so future
messages from the portal land there.
Pin an existing conversation:
Pin Gemini conversation .
Calls gemini_select_conversation. Pass an empty string or null to revert to
automatic mode (most recently active conversation).
Check the active conversation:
Which Gemini conversation is selected?
Calls gemini_get_selected_conversation.
Support
If this project is useful to you, you can support it at buymeacoffee.com/infinition.
Star History
License
Released under the MIT License.