feat(connect): dedicated Claude.ai / ChatGPT browser connect picker
- Replace single 'Connect to Claude / ChatGPT' button with a modal picker offering Claude.ai web, Claude Desktop, Codex CLI, and ChatGPT/GPT Actions. - Add /oauth/connect-claude-ai backend route that redirects to Anthropic's official https://claude.ai/api/mcp/auth_callback OAuth callback. - Update MCP callback result page with browser-specific instructions for Claude.ai web, Claude Desktop, ChatGPT/GPT Actions, and Codex CLI. - Deploy new app and hermes images to K8s.
This commit is contained in:
@@ -15,7 +15,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: squaremcp-app
|
||||
image: localhost:32000/squaremcp-app@sha256:88c9163b49a881b2d8e59f46d66297902109026d138e9562b9fcc1bb0f4ab4d6
|
||||
image: localhost:32000/squaremcp-app@sha256:9c2601dd74bfca9f22350a38dc616eb8a76580090587803911bb2e5633ace361
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
|
||||
@@ -252,9 +252,71 @@ logoutBtn.addEventListener('click', async () => {
|
||||
showLogin();
|
||||
});
|
||||
|
||||
// Connect MCP Client — start the browser OAuth flow
|
||||
// Connect MCP Client — show picker for Claude.ai / ChatGPT / desktop / CLI
|
||||
document.getElementById('connect-mcp-btn')?.addEventListener('click', () => {
|
||||
window.open(`${API_BASE}/oauth/connect-mcp`, '_blank', 'width=560,height=600,noopener');
|
||||
openModal(renderMcpClientPicker());
|
||||
});
|
||||
|
||||
function renderMcpClientPicker() {
|
||||
return `
|
||||
<div class="mcp-picker">
|
||||
<h3>Connect an AI client</h3>
|
||||
<p class="picker-subtitle">Choose where you want to use SquareMCP tools.</p>
|
||||
|
||||
<div class="picker-option">
|
||||
<div class="picker-meta">
|
||||
<div class="picker-title">Claude.ai (web)</div>
|
||||
<div class="picker-desc">Use SquareMCP directly in your browser at claude.ai.</div>
|
||||
</div>
|
||||
<a class="btn btn-primary" href="${API_BASE}/oauth/connect-claude-ai" target="_blank" rel="noopener" onclick="window.closeMcpPicker && window.closeMcpPicker()">Connect</a>
|
||||
</div>
|
||||
|
||||
<div class="picker-option">
|
||||
<div class="picker-meta">
|
||||
<div class="picker-title">Claude Desktop</div>
|
||||
<div class="picker-desc">macOS / Windows app with local MCP config.</div>
|
||||
</div>
|
||||
<button class="btn btn-primary" data-connect="claude-desktop">Connect</button>
|
||||
</div>
|
||||
|
||||
<div class="picker-option">
|
||||
<div class="picker-meta">
|
||||
<div class="picker-title">Codex CLI / OpenCode</div>
|
||||
<div class="picker-desc">Terminal-based agents (OpenAI, opencode).</div>
|
||||
</div>
|
||||
<button class="btn btn-primary" data-connect="codex">Connect</button>
|
||||
</div>
|
||||
|
||||
<div class="picker-option">
|
||||
<div class="picker-meta">
|
||||
<div class="picker-title">ChatGPT (web)</div>
|
||||
<div class="picker-desc">Copy the OpenAPI spec URL for GPT Actions.</div>
|
||||
</div>
|
||||
<button class="btn btn-secondary" data-connect="chatgpt">Get URL</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
window.closeMcpPicker = closeModal;
|
||||
|
||||
modalBody.addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('[data-connect]');
|
||||
if (!btn) return;
|
||||
const type = btn.dataset.connect;
|
||||
if (type === 'claude-desktop' || type === 'codex') {
|
||||
window.open(`${API_BASE}/oauth/connect-mcp`, '_blank', 'width=560,height=600,noopener');
|
||||
} else if (type === 'chatgpt') {
|
||||
openModal(`
|
||||
<div class="mcp-picker">
|
||||
<h3>ChatGPT / GPT Actions</h3>
|
||||
<p class="picker-subtitle">ChatGPT browser does not yet support native MCP. Use this OpenAPI spec URL in a GPT Action:</p>
|
||||
<div class="token-box" style="margin:16px 0;">${API_BASE}/openapi.json</div>
|
||||
<p class="picker-subtitle">Set authentication to <strong>Bearer token</strong> and paste your API key from <em>Settings → API Keys</em>.</p>
|
||||
<button class="btn btn-primary" onclick="window.open('${API_BASE}/openapi.json','_blank')">Open spec</button>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
// Password reset request
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
<section class="welcome">
|
||||
<h2>Connect your accounts</h2>
|
||||
<p>Connect once. Then ask Claude or ChatGPT to post, search your notes, or send email — without touching any of these apps.</p>
|
||||
<button id="connect-mcp-btn" class="btn btn-primary" style="margin-top:16px;">Connect to Claude / ChatGPT</button>
|
||||
<button id="connect-mcp-btn" class="btn btn-primary" style="margin-top:16px;" aria-label="Connect Claude.ai, ChatGPT, Claude Desktop, or Codex CLI" title="Connect Claude.ai, ChatGPT, Claude Desktop, or Codex CLI">Connect AI Client</button>
|
||||
</section>
|
||||
|
||||
<section class="usage-bar" id="usage-bar">
|
||||
|
||||
@@ -751,3 +751,66 @@ body {
|
||||
text-align: center;
|
||||
min-height: 18px;
|
||||
}
|
||||
|
||||
|
||||
/* MCP client picker modal */
|
||||
.mcp-picker h3 {
|
||||
margin: 0 0 6px;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.picker-subtitle {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
margin: 0 0 20px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.picker-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
margin-bottom: 12px;
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
.picker-option:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.picker-meta {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.picker-title {
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.picker-desc {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.picker-option .btn {
|
||||
white-space: nowrap;
|
||||
padding: 8px 14px;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.token-box {
|
||||
background: var(--background);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: 12px;
|
||||
font-family: 'SF Mono', monospace;
|
||||
font-size: 0.85rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user