Skip to content

Commit 15bbb75

Browse files
Merge pull request #175 from avi1mizrahi/main
Add Bearer Token Support
2 parents 7caf6f8 + dbd6169 commit 15bbb75

File tree

4 files changed

+63
-12
lines changed

4 files changed

+63
-12
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ CLIENT_PORT=8080 SERVER_PORT=9000 npx @modelcontextprotocol/inspector node build
3838

3939
For more details on ways to use the inspector, see the [Inspector section of the MCP docs site](https://modelcontextprotocol.io/docs/tools/inspector). For help with debugging, see the [Debugging guide](https://modelcontextprotocol.io/docs/tools/debugging).
4040

41+
### Authentication
42+
43+
The inspector supports bearer token authentication for SSE connections. Enter your token in the UI when connecting to an MCP server, and it will be sent in the Authorization header.
44+
4145
### From this repository
4246

4347
If you're working on the inspector itself:

client/src/App.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ const App = () => {
9797
>([]);
9898
const [roots, setRoots] = useState<Root[]>([]);
9999
const [env, setEnv] = useState<Record<string, string>>({});
100+
const [bearerToken, setBearerToken] = useState<string>(() => {
101+
return localStorage.getItem("lastBearerToken") || "";
102+
});
100103

101104
const [pendingSampleRequests, setPendingSampleRequests] = useState<
102105
Array<
@@ -164,6 +167,7 @@ const App = () => {
164167
args,
165168
sseUrl,
166169
env,
170+
bearerToken,
167171
proxyServerUrl: PROXY_SERVER_URL,
168172
onNotification: (notification) => {
169173
setNotifications((prev) => [...prev, notification as ServerNotification]);
@@ -199,6 +203,10 @@ const App = () => {
199203
localStorage.setItem("lastTransportType", transportType);
200204
}, [transportType]);
201205

206+
useEffect(() => {
207+
localStorage.setItem("lastBearerToken", bearerToken);
208+
}, [bearerToken]);
209+
202210
// Auto-connect if serverUrl is provided in URL params (e.g. after OAuth callback)
203211
useEffect(() => {
204212
const serverUrl = params.get("serverUrl");
@@ -418,6 +426,8 @@ const App = () => {
418426
setSseUrl={setSseUrl}
419427
env={env}
420428
setEnv={setEnv}
429+
bearerToken={bearerToken}
430+
setBearerToken={setBearerToken}
421431
onConnect={connectMcpServer}
422432
stdErrNotifications={stdErrNotifications}
423433
/>

client/src/components/Sidebar.tsx

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ interface SidebarProps {
3535
setSseUrl: (url: string) => void;
3636
env: Record<string, string>;
3737
setEnv: (env: Record<string, string>) => void;
38+
bearerToken: string;
39+
setBearerToken: (token: string) => void;
3840
onConnect: () => void;
3941
stdErrNotifications: StdErrNotification[];
4042
}
@@ -51,11 +53,14 @@ const Sidebar = ({
5153
setSseUrl,
5254
env,
5355
setEnv,
56+
bearerToken,
57+
setBearerToken,
5458
onConnect,
5559
stdErrNotifications,
5660
}: SidebarProps) => {
5761
const [theme, setTheme] = useTheme();
5862
const [showEnvVars, setShowEnvVars] = useState(false);
63+
const [showBearerToken, setShowBearerToken] = useState(false);
5964
const [shownEnvVars, setShownEnvVars] = useState<Set<string>>(new Set());
6065

6166
return (
@@ -110,15 +115,43 @@ const Sidebar = ({
110115
</div>
111116
</>
112117
) : (
113-
<div className="space-y-2">
114-
<label className="text-sm font-medium">URL</label>
115-
<Input
116-
placeholder="URL"
117-
value={sseUrl}
118-
onChange={(e) => setSseUrl(e.target.value)}
119-
className="font-mono"
120-
/>
121-
</div>
118+
<>
119+
<div className="space-y-2">
120+
<label className="text-sm font-medium">URL</label>
121+
<Input
122+
placeholder="URL"
123+
value={sseUrl}
124+
onChange={(e) => setSseUrl(e.target.value)}
125+
className="font-mono"
126+
/>
127+
</div>
128+
<div className="space-y-2">
129+
<Button
130+
variant="outline"
131+
onClick={() => setShowBearerToken(!showBearerToken)}
132+
className="flex items-center w-full"
133+
>
134+
{showBearerToken ? (
135+
<ChevronDown className="w-4 h-4 mr-2" />
136+
) : (
137+
<ChevronRight className="w-4 h-4 mr-2" />
138+
)}
139+
Authentication
140+
</Button>
141+
{showBearerToken && (
142+
<div className="space-y-2">
143+
<label className="text-sm font-medium">Bearer Token</label>
144+
<Input
145+
placeholder="Bearer Token"
146+
value={bearerToken}
147+
onChange={(e) => setBearerToken(e.target.value)}
148+
className="font-mono"
149+
type="password"
150+
/>
151+
</div>
152+
)}
153+
</div>
154+
</>
122155
)}
123156
{transportType === "stdio" && (
124157
<div className="space-y-2">

client/src/lib/hooks/useConnection.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ interface UseConnectionOptions {
3838
sseUrl: string;
3939
env: Record<string, string>;
4040
proxyServerUrl: string;
41+
bearerToken?: string;
4142
requestTimeout?: number;
4243
onNotification?: (notification: Notification) => void;
4344
onStdErrNotification?: (notification: Notification) => void;
@@ -58,6 +59,7 @@ export function useConnection({
5859
sseUrl,
5960
env,
6061
proxyServerUrl,
62+
bearerToken,
6163
requestTimeout = DEFAULT_REQUEST_TIMEOUT_MSEC,
6264
onNotification,
6365
onStdErrNotification,
@@ -229,9 +231,11 @@ export function useConnection({
229231
// Inject auth manually instead of using SSEClientTransport, because we're
230232
// proxying through the inspector server first.
231233
const headers: HeadersInit = {};
232-
const tokens = await authProvider.tokens();
233-
if (tokens) {
234-
headers["Authorization"] = `Bearer ${tokens.access_token}`;
234+
235+
// Use manually provided bearer token if available, otherwise use OAuth tokens
236+
const token = bearerToken || (await authProvider.tokens())?.access_token;
237+
if (token) {
238+
headers["Authorization"] = `Bearer ${token}`;
235239
}
236240

237241
const clientTransport = new SSEClientTransport(backendUrl, {

0 commit comments

Comments
 (0)