Server Configuration¶
Configure how agents connect to MCP servers using StdioServerSpec for local servers and HTTPServerSpec for remote ones.
Quick Example¶
Concepts¶
Every Promptise agent receives a servers dict that maps a human-readable name to a server specification. The agent connects to each server at startup, discovers its tools, and makes them available to the LLM.
There are two spec types:
StdioServerSpec-- launches a local process and communicates over stdin/stdout. Best for local development and bundled servers.HTTPServerSpec-- connects to a remote server over HTTP, Streamable HTTP, or SSE. Best for production deployments and shared services.
Both are Pydantic models with strict validation (extra="forbid"), so typos in field names are caught immediately.
StdioServerSpec¶
Use StdioServerSpec when the MCP server is a local process that the agent should launch and manage.
from promptise.config import StdioServerSpec
spec = StdioServerSpec(
command="python",
args=["-m", "mypackage.server", "--port", "0"],
env={"API_KEY": "sk-..."},
cwd="/path/to/project",
keep_alive=True,
)
Fields¶
| Field | Type | Default | Description |
|---|---|---|---|
command |
str |
required | Executable to launch (e.g. "python", "node", "npx"). |
args |
list[str] |
[] |
Positional arguments for the process. |
env |
dict[str, str] |
{} |
Environment variables set for the child process. |
cwd |
str \| None |
None |
Working directory for the process. |
keep_alive |
bool |
True |
Whether the client should maintain a persistent session. |
Examples¶
HTTPServerSpec¶
Use HTTPServerSpec for remote MCP servers accessible over the network. Supports three transport protocols and multiple authentication methods.
from promptise.config import HTTPServerSpec
spec = HTTPServerSpec(
url="https://mcp.example.com/mcp",
bearer_token="eyJhbGciOiJIUzI1NiIs...",
)
Fields¶
| Field | Type | Default | Description |
|---|---|---|---|
url |
str |
required | Full endpoint URL (e.g. "http://127.0.0.1:8080/mcp"). |
transport |
"http" \| "streamable-http" \| "sse" |
"http" |
Transport protocol. |
headers |
dict[str, str] |
{} |
Extra HTTP headers sent on every request. |
bearer_token |
str \| None |
None |
Pre-issued Bearer token. Automatically injected as Authorization: Bearer <token>. |
api_key |
str \| None |
None |
Pre-shared API key. Automatically injected as x-api-key: <key>. |
audience |
str \| None |
None |
Resource audience this server expects; with an agent identity and no bearer_token, a credential for this audience is presented. |
forward_caller_token |
bool \| None |
None |
When an invocation's CallerContext has a bearer_token, call this server's tools with that token (one MCP session per caller) instead of bearer_token / the agent identity. None: forward, unless the server has an API key (api_key or an x-api-key header), which wins. True: always forward. False: never; use it for servers that must not receive your users' tokens. See Per-user tokens. |
auth |
str \| None |
None |
Legacy auth hint (kept for backward compatibility). |
Per-user tokens¶
The credentials above authenticate the agent: they open its connection to the server and are used to discover the server's tools. When an invocation carries a user's token, the tool calls are made as that user:
agent = await build_agent(
model="openai:gpt-5-mini",
servers={
"crm": HTTPServerSpec(url="https://crm.internal/mcp", bearer_token=SERVICE_TOKEN),
"search": HTTPServerSpec(
url="https://search.vendor.example/mcp",
api_key=VENDOR_KEY,
forward_caller_token=False, # third party: never send our users' tokens
),
},
)
caller = CallerContext(user_id="alice", tenant_id="acme", bearer_token=alice_jwt)
await agent.ainvoke({"messages": [...]}, caller=caller)
# crm tools: Authorization: Bearer <alice_jwt> (a session opened for Alice)
# search tools: x-api-key: <VENDOR_KEY> (the agent's own session)
Each distinct caller token gets its own MCP session, opened on first use,
reused by that caller's later calls, and closed after five idle minutes;
concurrent invocations never share a session or a header. The forwarded
token replaces any Authorization header from bearer_token or
headers. Invocations without a caller token use the spec's credentials.
StdioServerSpec servers have no request headers and never receive a
caller token.
Which credential a server sees on a tool call:
| Spec | Caller has a token | Caller has no token |
|---|---|---|
forward_caller_token=False |
spec credential | spec credential |
api_key / x-api-key header, forward_caller_token unset |
spec credential (the API key wins) | spec credential |
bearer_token, an Authorization header, or nothing |
caller's token | spec credential / agent identity |
api_key and forward_caller_token=True |
caller's token and the API key | spec credential |
An API key is an explicit credential for that server, so by default it
wins: the caller's bearer is not sent. (It cannot replace the key: it
would travel next to it, and a gate that checks the bearer first, as a
Promptise server's does, answers 401.) Set forward_caller_token=True
only when the server is meant to authenticate your users: both headers
are then sent and the server decides which one counts. A Promptise server
checks the bearer first, so the user's token must be valid there.
Transport Protocols¶
| Transport | When to Use |
|---|---|
"http" |
Default. MCP Streamable HTTP — the current MCP transport, served by Promptise servers at /mcp. Responses to a request can stream (progress, incremental results) and the server can send notifications. |
"streamable-http" |
An alias of "http": the same Streamable HTTP client, accepted because other MCP tools spell the transport this way. |
"sse" |
The legacy HTTP+SSE transport (an event stream at /sse, posts to /messages/). Use it only for servers that do not speak Streamable HTTP. |
Point the URL at the MCP endpoint itself — http://host:8080/mcp for a Promptise server, not http://host:8080. A URL without the endpoint fails at connect time with MCPConnectionRejectedError (404 Not Found, with a hint to check the /mcp path).
Authentication¶
HTTPServerSpec supports three authentication approaches. Use whichever matches your server's requirements.
Token source
Tokens should be obtained from your Identity Provider (Auth0, Keycloak, Okta, etc.) or from the MCP server's built-in token endpoint. The agent never generates tokens itself.
Combining Multiple Servers¶
An agent can connect to any number of servers simultaneously. Each server's tools are discovered independently and merged into a single toolset.
from promptise import build_agent
from promptise.config import StdioServerSpec, HTTPServerSpec
agent = await build_agent(
servers={
"filesystem": StdioServerSpec(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "/data"],
),
"database": HTTPServerSpec(
url="http://localhost:9000/mcp",
api_key="db-secret",
),
"search": HTTPServerSpec(
url="https://search.example.com/mcp",
bearer_token="eyJ...",
),
},
model="openai:gpt-5-mini",
)
Tools from all three servers are available to the agent as a flat list. If two servers expose a tool with the same name, both are included -- the LLM decides which to call based on their descriptions.
API Summary¶
| Symbol | Import | Description |
|---|---|---|
StdioServerSpec |
from promptise.config import StdioServerSpec |
Local process server launched via stdin/stdout. |
HTTPServerSpec |
from promptise.config import HTTPServerSpec |
Remote server over HTTP, Streamable HTTP, or SSE. |
ServerSpec |
from promptise.config import ServerSpec |
Union type: StdioServerSpec \| HTTPServerSpec. |
Validation catches typos
Both specs use extra="forbid" in their Pydantic config. Passing an unknown field like commnad instead of command raises a validation error immediately rather than silently ignoring it.
Empty servers dict
Passing servers={} is valid but the agent will have no MCP tools. This is useful when you rely solely on extra_tools or cross_agents, but if unintentional, double-check your configuration.
What's Next?¶
- Building Agents -- full
build_agent()parameter reference. - SuperAgent Files -- define server configs declaratively in YAML.
- Authentication & Security -- securing your MCP servers with JWT and API keys.
Learn the concept
- How to Connect MCP Servers to Your AI Agent in Python -- Connect local and remote MCP servers to an agent, step by step.
- MCP Transports: stdio vs Streamable HTTP vs SSE (Python) -- stdio vs Streamable HTTP vs SSE, and which to use where.