Skip to content

Commit dd16a2e

Browse files
adds optional stateless configuration (#222)
* optional statelessness * Update config.ts * Update docker-compose.yml * Update documentation --------- Co-authored-by: Harold Spencer Jr. <hspencer@brave.com>
1 parent 1971bc0 commit dd16a2e

File tree

5 files changed

+50
-13
lines changed

5 files changed

+50
-13
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,12 @@ The server supports the following environment variables:
114114

115115
- `BRAVE_API_KEY`: Your Brave Search API key (required)
116116
- `BRAVE_MCP_TRANSPORT`: Transport mode ("http" or "stdio", default: "stdio")
117-
- `BRAVE_MCP_PORT`: HTTP server port (default: 8080)
117+
- `BRAVE_MCP_PORT`: HTTP server port (default: 8000)
118118
- `BRAVE_MCP_HOST`: HTTP server host (default: "0.0.0.0")
119119
- `BRAVE_MCP_LOG_LEVEL`: Desired logging level("debug", "info", "notice", "warning", "error", "critical", "alert", or "emergency", default: "info")
120120
- `BRAVE_MCP_ENABLED_TOOLS`: When used, specifies a whitelist for supported tools
121121
- `BRAVE_MCP_DISABLED_TOOLS`: When used, specifies a blacklist for supported tools
122+
- `BRAVE_MCP_STATELESS`: HTTP stateless mode (default: "true"). When running on Amazon Bedrock Agentcore, set to "true".
122123

123124
### Command Line Options
124125

@@ -133,6 +134,7 @@ Options:
133134
--logging-level <string> Desired logging level (one of _debug_, _info_, _notice_, _warning_, _error_, _critical_, _alert_, or _emergency_)
134135
--enabled-tools Tools whitelist (only the specified tools will be enabled)
135136
--disabled-tools Tools blacklist (included tools will be disabled)
137+
--stateless <boolean> HTTP Stateless flag
136138
```
137139

138140
## Installation

docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ services:
1111
- BRAVE_API_KEY
1212
- BRAVE_MCP_TRANSPORT=http
1313
- BRAVE_MCP_PORT=8080
14+
- BRAVE_MCP_STATELESS
1415
- BRAVE_MCP_HOST=0.0.0.0
1516
- BRAVE_MCP_LOG_LEVEL=info
1617
- BRAVE_MCP_ENABLED_TOOLS

marketplace-revision-release.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@
4343
"Description": "MCP protocol transport mode. Supported values are \"http\" or \"stdio\", however Bedrock Agentcore only supports \"http\" (reference https://docs.aws.amazon.com/marketplace/latest/userguide/bedrock-agentcore-runtime.html#agentcore-container-requirements)."
4444
},
4545
{
46-
"DefaultValue": "8080",
46+
"DefaultValue": "8000",
4747
"Name": "BRAVE_MCP_PORT",
48-
"Description": "HTTP server port (default: 8080). Mandatory port for Bedrock Agentcore is 8080 (reference https://docs.aws.amazon.com/marketplace/latest/userguide/bedrock-agentcore-runtime.html#agentcore-container-requirements)."
48+
"Description": "HTTP server port (default: 8000). Mandatory port for Bedrock Agentcore is 8000 (reference https://docs.aws.amazon.com/marketplace/latest/userguide/bedrock-agentcore-runtime.html#agentcore-container-requirements)."
4949
},
5050
{
5151
"DefaultValue": "0.0.0.0",
@@ -64,6 +64,11 @@
6464
{
6565
"Name": "BRAVE_MCP_DISABLED_TOOLS",
6666
"Description": "*Optional* When used, specifies a blacklist for supported tools"
67+
},
68+
{
69+
"DefaultValue": "true",
70+
"Name": "BRAVE_MCP_STATELESS",
71+
"Description": "Sets HTTP Stateless mode (default: true). When deploying on Bedrock Agentcore, this should be set to true."
6772
}
6873
]
6974
}

src/config.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ export const configSchema = z.object({
3434
.default('info')
3535
.describe('Desired logging level')
3636
.optional(),
37+
stateless: z
38+
.boolean()
39+
.default(false)
40+
.describe('Whether the server should be stateless')
41+
.optional(),
3742
});
3843

3944
export type SmitheryConfig = z.infer<typeof configSchema>;
@@ -46,6 +51,7 @@ type Configuration = {
4651
loggingLevel: LoggingLevel;
4752
enabledTools: string[];
4853
disabledTools: string[];
54+
stateless: boolean;
4955
};
5056

5157
const state: Configuration & { ready: boolean } = {
@@ -57,6 +63,7 @@ const state: Configuration & { ready: boolean } = {
5763
ready: false,
5864
enabledTools: [],
5965
disabledTools: [],
66+
stateless: false,
6067
};
6168

6269
export function isToolPermittedByUser(toolName: string): boolean {
@@ -77,12 +84,12 @@ export function getOptions(): Configuration | false {
7784
.option(
7885
'--enabled-tools <names...>',
7986
'tools to enable',
80-
process.env.BRAVE_MCP_ENABLED_TOOLS?.split(' ') ?? []
87+
process.env.BRAVE_MCP_ENABLED_TOOLS?.trim().split(' ') ?? []
8188
)
8289
.option(
8390
'--disabled-tools <names...>',
8491
'tools to disable',
85-
process.env.BRAVE_MCP_DISABLED_TOOLS?.split(' ') ?? []
92+
process.env.BRAVE_MCP_DISABLED_TOOLS?.trim().split(' ') ?? []
8693
)
8794
.option(
8895
'--port <number>',
@@ -94,6 +101,11 @@ export function getOptions(): Configuration | false {
94101
'desired host for HTTP transport',
95102
process.env.BRAVE_MCP_HOST ?? '0.0.0.0'
96103
)
104+
.option(
105+
'--stateless <boolean>',
106+
'whether the server should be stateless',
107+
process.env.BRAVE_MCP_STATELESS === 'true' ? true : false
108+
)
97109
.allowUnknownOption()
98110
.parse(process.argv);
99111

@@ -108,7 +120,11 @@ export function getOptions(): Configuration | false {
108120
return false;
109121
}
110122

111-
if ([...enabledTools, ...disabledTools].some((t) => !toolNames.includes(t))) {
123+
if (
124+
[...enabledTools, ...disabledTools].some(
125+
(t) => t.trim().length > 0 && !toolNames.includes(t.trim())
126+
)
127+
) {
112128
console.error(`Invalid tool name used. Must be one of: ${toolNames.join(', ')}`);
113129
return false;
114130
}
@@ -149,6 +165,9 @@ export function getOptions(): Configuration | false {
149165
}
150166
}
151167

168+
// Normalize stateless to boolean (CLI passes it as string)
169+
options.stateless = options.stateless === true || options.stateless === 'true';
170+
152171
// Update state
153172
state.braveApiKey = options.braveApiKey;
154173
state.transport = options.transport;
@@ -157,6 +176,7 @@ export function getOptions(): Configuration | false {
157176
state.loggingLevel = options.loggingLevel;
158177
state.enabledTools = options.enabledTools;
159178
state.disabledTools = options.disabledTools;
179+
state.stateless = options.stateless;
160180
state.ready = true;
161181

162182
return options as Configuration;

src/protocols/http.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,22 @@ const getTransport = async (request: Request): Promise<StreamableHTTPServerTrans
3737
return transport;
3838
}
3939

40-
// Otherwise, start a new transport/session
41-
const transport = new StreamableHTTPServerTransport({
42-
sessionIdGenerator: () => randomUUID(),
43-
onsessioninitialized: (sessionId) => {
44-
transports.set(sessionId, transport);
45-
},
46-
});
40+
let transport: StreamableHTTPServerTransport;
41+
42+
if (config.stateless) {
43+
// Some contexts (e.g. AgentCore) may prefer or require a stateless transport
44+
transport = new StreamableHTTPServerTransport({
45+
sessionIdGenerator: undefined,
46+
});
47+
} else {
48+
// Otherwise, start a new transport/session
49+
transport = new StreamableHTTPServerTransport({
50+
sessionIdGenerator: () => randomUUID(),
51+
onsessioninitialized: (sessionId) => {
52+
transports.set(sessionId, transport);
53+
},
54+
});
55+
}
4756

4857
const mcpServer = createMcpServer();
4958
await mcpServer.connect(transport);

0 commit comments

Comments
 (0)