gmail proxy tool with token refresh, claude pro bearer auth, pi --list-models stderr fallback, tool object input type

- add getValidGoogleAccessToken helper and use it in email-cron, email account auth resolver, and the new gmail proxy
- POST /api/integrations/google/gmail-proxy forwards arbitrary gmail rest calls server-side, with auto-refreshed oauth
- pi-manager and claude user-instance inject OFFICER_API_URL + per-session JWT so tools can call back as the user
- claude anthropic proxy uses Authorization: Bearer + preserves any anthropic-beta headers (pro oauth tokens are rejected via x-api-key, and overwriting the beta header broke context_management)
- pi --list-models: fall back to stderr when stdout is empty (pi v0.73.1 writes the table to stderr)
- mcp tool server + pi tool loader: accept type: object inputs so json bodies stay structured

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 17:07:51 +00:00
co-authored by Claude Opus 4.7
parent 8a583da19b
commit 3540d53a00
10 changed files with 129 additions and 17 deletions
@@ -6,6 +6,8 @@ import { setMcpConfigPath } from './claude-manager';
import { SANDBOX_DATA } from '../sandbox';
import * as claudeManager from './claude-manager';
import { createSidecarConnector } from '../connect';
import { sign } from '../../jwt';
import { getUserByEmail } from 'officerdb';
const email = process.env.CLAUDE_USER_EMAIL;
if (!email) {
@@ -15,8 +17,20 @@ if (!email) {
const DATA_PATH = process.env.DATA_PATH ?? join(process.cwd(), 'data');
const API_URL = process.env.API_URL ?? `ws://127.0.0.1:${process.env.PORT ?? '5000'}`;
const OFFICER_API_URL = process.env.OFFICER_API_URL ?? `http://127.0.0.1:${process.env.PORT ?? '9010'}`;
const MCP_SERVER_SCRIPT = resolve(import.meta.dir, '../../mcp-tool-server.ts');
// Mint a long-lived JWT for this user so tools (e.g. gmail) can call back to dev-platform as them
const dbUser = await getUserByEmail(email);
if (!dbUser) {
console.error(`[user-instance] no user found for ${email}`);
process.exit(1);
}
const OFFICER_AUTH_TOKEN = await sign(
{ id: dbUser.id, email, username: dbUser.username, role: dbUser.role },
'30d',
);
const homeDir = join(DATA_PATH, email, 'home');
const globalToolsDir = join(DATA_PATH, 'tools');
const userToolsDir = join(DATA_PATH, email, 'tools');
@@ -73,6 +87,8 @@ function generateMcpConfig(): McpPaths {
PI_TOOLS_DIRS: sandboxToolsDirs,
OFFICER_EMAIL_DB: `${SANDBOX_DATA}/emails.db`,
MCP_TOOLS_LOG: `${SANDBOX_DATA}/logs/mcp-tools.log`,
OFFICER_API_URL,
OFFICER_AUTH_TOKEN,
},
},
},
@@ -91,6 +107,8 @@ function generateMcpConfig(): McpPaths {
PI_TOOLS_DIRS: hostToolsDirs,
OFFICER_EMAIL_DB: join(userRoot, 'emails.db'),
MCP_TOOLS_LOG: join(userRoot, 'logs', 'mcp-tools.log'),
OFFICER_API_URL,
OFFICER_AUTH_TOKEN,
},
},
},