Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 46 additions & 13 deletions commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import type { McpConfig, ServerEntry, McpPanelCallbacks, McpPanelResult } from "
import { getServerProvenance, writeDirectToolsConfig } from "./config.js";
import { lazyConnect, updateMetadataCache, updateStatusBar, getFailureAgeSeconds } from "./init.js";
import { loadMetadataCache } from "./metadata-cache.js";
import { getStoredTokens } from "./oauth-handler.js";
import { getStoredTokens, getStoredTokensSync } from "./oauth-handler.js";
import { performOAuthFlow } from "./oauth-flow.js";
import { buildToolMetadata } from "./tool-metadata.js";

export async function showStatus(state: McpExtensionState, ctx: ExtensionContext): Promise<void> {
Expand Down Expand Up @@ -143,21 +144,53 @@ export async function authenticateServer(
return;
}

const tokenPath = `~/.pi/agent/mcp-oauth/${serverName}/tokens.json`;
// Determine authorization server from config or URL
const url = new URL(definition.url);
const authorizationServer = definition.authorizationServer ?? `${url.protocol}//${url.host}`;

// Use configured client ID or default
const clientId = definition.clientId ?? "mcp";

// Determine scopes from server config
const scopes = definition.scopes ?? [];

ctx.ui.notify(
`OAuth setup for "${serverName}":\n\n` +
`1. Obtain an access token from your OAuth provider\n` +
`2. Create the token file:\n` +
` ${tokenPath}\n\n` +
`3. Add your token:\n` +
` {\n` +
` "access_token": "your-token-here",\n` +
` "token_type": "bearer"\n` +
` }\n\n` +
`4. Run /mcp reconnect to connect with the token`,
`Starting OAuth authentication for "${serverName}"...\n` +
`Authorization server: ${authorizationServer}\n` +
`Client ID: ${clientId}\n` +
`Scopes: ${scopes.join(", ") || "(none)"}\n\n` +
`A browser window will open. Please authorize the application.`,
"info"
);

const success = await performOAuthFlow(
serverName,
authorizationServer,
clientId,
scopes,
(message) => {
// Show in UI and log to console
ctx.ui.notify(message, "info");
console.log(`[OAuth ${serverName}] ${message}`);
}
);

if (success) {
ctx.ui.notify(
`Authentication successful for "${serverName}"!\n` +
`Run /mcp reconnect ${serverName} to connect.`,
"success"
);
} else {
ctx.ui.notify(
`Authentication failed for "${serverName}".\n` +
`Check above messages for details. Common issues:\n` +
`- Invalid client_id (needs app registration)\n` +
`- Redirect URI mismatch\n` +
`- Server doesn't support PKCE`,
"error"
);
}
}

export async function openMcpPanel(
Expand All @@ -176,7 +209,7 @@ export async function openMcpPanel(
},
getConnectionStatus: (serverName: string) => {
const definition = config.mcpServers[serverName];
if (definition?.auth === "oauth" && getStoredTokens(serverName) === undefined) {
if (definition?.auth === "oauth" && getStoredTokensSync(serverName) === undefined) {
return "needs-auth";
}
const connection = state.manager.getConnection(serverName);
Expand Down
Loading