Skip to content

Commit 73a7459

Browse files
kaheidtpunkpeye
andauthored
Adding headers passthrough documentation (#102)
* Adding headers passthrough documentation * Update README.md * grammar --------- Co-authored-by: Frank Fiegel <[email protected]>
1 parent 7f01430 commit 73a7459

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

README.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ A TypeScript framework for building [MCP](https://glama.ai/mcp) servers capable
1010

1111
- Simple Tool, Resource, Prompt definition
1212
- [Authentication](#authentication)
13+
- [Passing headers through context](#passing-headers-through-context)
1314
- [Sessions](#sessions)
1415
- [Image content](#returning-an-image)
1516
- [Audio content](#returning-an-audio)
@@ -1161,6 +1162,124 @@ server.addTool({
11611162
});
11621163
```
11631164

1165+
#### Passing Headers Through Context
1166+
1167+
If you are exposing your MCP server via HTTP, you may wish to allow clients to supply sensitive keys via headers, which can then be passed along to APIs that your tools interact with, allowing each client to supply their own API keys. This can be done by capturing the HTTP headers in the `authenticate` section and storing them in the session to be referenced by the tools later.
1168+
1169+
```ts
1170+
import { FastMCP } from 'fastmcp';
1171+
import { IncomingHttpHeaders } from 'http';
1172+
1173+
// Define the session data type
1174+
interface SessionData {
1175+
headers: IncomingHttpHeaders;
1176+
[key: string]: unknown; // Add index signature to satisfy Record<string, unknown>
1177+
}
1178+
1179+
// Create a server instance
1180+
const server = new FastMCP({
1181+
name: "My Server",
1182+
version: "1.0.0",
1183+
authenticate: async (request: any): Promise<SessionData> => {
1184+
// Authentication logic
1185+
return {
1186+
headers: request.headers
1187+
};
1188+
}
1189+
});
1190+
1191+
// Tool to display HTTP headers
1192+
server.addTool({
1193+
name: 'headerTool',
1194+
description: 'Reads HTTP headers from the request',
1195+
execute: async (args: any, context: any) => {
1196+
const session = context.session as SessionData;
1197+
const headers = session?.headers ?? {};
1198+
1199+
const getHeaderString = (header: string | string[] | undefined) =>
1200+
Array.isArray(header) ? header.join(', ') : header ?? 'N/A';
1201+
1202+
const userAgent = getHeaderString(headers['user-agent']);
1203+
const authorization = getHeaderString(headers['authorization']);
1204+
return `User-Agent: ${userAgent}\nAuthorization: ${authorization}\nAll Headers: ${JSON.stringify(headers, null, 2)}`;
1205+
},
1206+
});
1207+
1208+
// Start the server
1209+
server.start({
1210+
transportType: "httpStream",
1211+
httpStream: {
1212+
endpoint: '/mcp',
1213+
port: 8080,
1214+
},
1215+
});
1216+
```
1217+
1218+
A client that would connect to this may look something like this:
1219+
1220+
```ts
1221+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
1222+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
1223+
1224+
const transport = new StreamableHTTPClientTransport(
1225+
new URL(`http://localhost:8080/mcp`),
1226+
{
1227+
requestInit: {
1228+
headers: {
1229+
'Authorization': 'Test 123'
1230+
}
1231+
}
1232+
}
1233+
);
1234+
1235+
const client = new Client(
1236+
{
1237+
name: "example-client",
1238+
version: "1.0.0",
1239+
}
1240+
);
1241+
1242+
(async () => {
1243+
await client.connect(transport);
1244+
1245+
// Call a tool
1246+
const result = await client.callTool({
1247+
name: "headerTool",
1248+
arguments: {
1249+
arg1: "value"
1250+
}
1251+
});
1252+
1253+
console.log("Tool result:", result);
1254+
})().catch(console.error);
1255+
```
1256+
1257+
What would show up in the console after the client runs is something like this:
1258+
1259+
```
1260+
Tool result: {
1261+
content: [
1262+
{
1263+
type: 'text',
1264+
text: 'User-Agent: node\n' +
1265+
'Authorization: Test 123\n' +
1266+
'All Headers: {\n' +
1267+
' "host": "localhost:8080",\n' +
1268+
' "connection": "keep-alive",\n' +
1269+
' "authorization": "Test 123",\n' +
1270+
' "content-type": "application/json",\n' +
1271+
' "accept": "application/json, text/event-stream",\n' +
1272+
' "accept-language": "*",\n' +
1273+
' "sec-fetch-mode": "cors",\n' +
1274+
' "user-agent": "node",\n' +
1275+
' "accept-encoding": "gzip, deflate",\n' +
1276+
' "content-length": "163"\n' +
1277+
'}'
1278+
}
1279+
]
1280+
}
1281+
```
1282+
11641283
### Providing Instructions
11651284

11661285
You can provide instructions to the server using the `instructions` option:

0 commit comments

Comments
 (0)