xiaohongshu
xiaohongshu
google-oauth-integration
Complete Google OAuth integration architecture including token storage and debugging
Full skill instructions
This skill documents the complete Google OAuth integration architecture in Orient, including token storage, tool registration, and debugging procedures.
Use this skill when:
Google OAuth tokens are stored in JSON files at:
{cwd}/data/oauth-tokens/google-oauth.json
CRITICAL: The path is resolved using process.cwd(), meaning different packages look in different locations:
packages/dashboard/data/oauth-tokens/google-oauth.jsonpackages/bot-slack/data/oauth-tokens/google-oauth.jsonpackages/bot-whatsapp/data/oauth-tokens/google-oauth.jsondata/oauth-tokens/google-oauth.jsonSince the dashboard is typically where users connect their Google accounts, other packages need symlinks to access the same tokens:
# For bot-slack
mkdir -p packages/bot-slack/data/oauth-tokens
ln -sf $(pwd)/packages/dashboard/data/oauth-tokens/google-oauth.json \
packages/bot-slack/data/oauth-tokens/google-oauth.json
# For bot-whatsapp
mkdir -p packages/bot-whatsapp/data/oauth-tokens
ln -sf $(pwd)/packages/dashboard/data/oauth-tokens/google-oauth.json \
packages/bot-whatsapp/data/oauth-tokens/google-oauth.json
# For project root (used by MCP servers)
mkdir -p data/oauth-tokens
ln -sf $(pwd)/packages/dashboard/data/oauth-tokens/google-oauth.json \
data/oauth-tokens/google-oauth.json
{
"accounts": {
"[email protected]": {
"email": "[email protected]",
"displayName": "User Name",
"accessToken": "ya29...",
"refreshToken": "1//...",
"expiresAt": 1768578677699,
"scopes": [
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/gmail.modify"
],
"connectedAt": 1768552923717,
"lastRefreshAt": 1768575078699
}
},
"pendingStates": {}
}
Required environment variables in .env:
# OAuth Client Credentials (from Google Cloud Console)
GOOGLE_OAUTH_CLIENT_ID=<your-client-id>.apps.googleusercontent.com
GOOGLE_OAUTH_CLIENT_SECRET=GOCSPX-<your-secret>
# Callback URL (must match Google Cloud Console)
GOOGLE_OAUTH_CALLBACK_URL=http://localhost/api/auth/google/callback
The OAuth service loads credentials in this priority order:
GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET)credentials/client_secret_*.jsonOrient has two tool registration systems:
ToolRegistry (Discovery only)
packages/agents/src/services/toolRegistry.tsdiscover_tools for listing available toolsToolExecutorRegistry (Execution)
packages/agents/src/services/toolRegistry.tsexecuteToolCallFromRegistry() in packages/mcp-servers/src/tool-executor.tsTo add a new Google tool, register it in the registerGoogleToolHandlers() function:
// In packages/agents/src/services/toolRegistry.ts
function registerGoogleToolHandlers(registry: ToolExecutorRegistry): void {
const registerHandlers = async () => {
const { getCalendarService, getGoogleOAuthService } =
await import('@orientbot/integrations/google');
// Register handler
registry.registerHandler('google_calendar_list_events', async (args) => {
const calendar = getCalendarService();
const events = await calendar.listEvents(options, accountEmail);
return createToolResult(JSON.stringify(events, null, 2));
});
};
void registerHandlers();
}
| Aspect | Legacy (mcp-server.ts) | Modern (ToolExecutorRegistry) |
|---|---|---|
| Location | packages/mcp-servers/src/mcp-server.ts | packages/agents/src/services/toolRegistry.ts |
| Pattern | Giant switch statement | Handler registration |
| Used by | Direct MCP server | assistant-server via base-server |
| Status | Deprecated | Preferred |
Important: The assistant-server (used by Slack/WhatsApp bots) uses base-server.ts which ONLY uses ToolExecutorRegistry. It does NOT fall back to the legacy switch statement unless setLegacyExecutor() is called.
The OAuth service in packages/integrations/src/google/oauth.ts handles automatic token refresh:
async getAuthClient(email: string): Promise<Auth.OAuth2Client> {
const account = this.data.accounts[email];
// Check if token needs refresh (expired or expiring in < 5 min)
if (Date.now() > account.expiresAt - 5 * 60 * 1000) {
const { credentials } = await client.refreshAccessToken();
account.accessToken = credentials.access_token;
account.expiresAt = credentials.expiry_date;
this.saveData();
}
return client;
}
Key points:
refresh_token from initial OAuth consentWhen Google tools return {"error":"Unknown tool: google_calendar_list_events"}:
# Tool should appear in discover_tools output
curl -X POST http://localhost:4099/... -d '{"tool":"discover_tools","args":{"mode":"search","query":"calendar"}}'
If tool appears in discovery but not execution, it's registered in ToolRegistry but not ToolExecutorRegistry.
Look for the tool in packages/agents/src/services/toolRegistry.ts:
// Should see this in registerGoogleToolHandlers():
registry.registerHandler('google_calendar_list_events', async (args) => { ... });
# Rebuild affected packages
pnpm --filter @orientbot/agents build
pnpm --filter @orientbot/mcp-servers build
# Copy to root dist (used by OpenCode)
cp packages/mcp-servers/dist/*.js dist/mcp-servers/
# Kill existing MCP server processes
ps aux | grep "assistant-server\|coding-server" | grep -v grep | awk '{print $2}' | xargs kill
# OpenCode will spawn fresh processes on next tool call
tail -f logs/mcp-debug-*.log | grep -i "calendar\|google\|unknown"
Look for:
"Registered tool" - Tool was registered"Unknown tool" - Tool not found in any executorSymptom: "No Google account connected" Cause: Token file not found at CWD path Fix: Create symlinks as documented above
Symptom: "Failed to refresh token" Cause: OAuth credentials not accessible Fix: Ensure GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET are set
Symptom: {"error":"Unknown tool: google_calendar_list_events"}
Cause: Tool not registered in ToolExecutorRegistry
Fix: Add handler in registerGoogleToolHandlers() and rebuild
Symptom: Changes not taking effect Cause: Old MCP server process still running Fix: Kill old processes, OpenCode will spawn new ones
| File | Purpose |
|---|---|
packages/integrations/src/google/oauth.ts | OAuth service, token storage |
packages/integrations/src/google/calendar.ts | Calendar service implementation |
packages/agents/src/services/toolRegistry.ts | Tool discovery + executor registration |
packages/mcp-servers/src/tool-executor.ts | Tool execution entry point |
packages/mcp-servers/src/base-server.ts | MCP server using executor registry |
packages/mcp-servers/src/mcp-server.ts | Legacy MCP server with switch statement |
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience