Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
d7d1496
feat: add MCP 2.0 (2026-07-28) foundation and stateless HTTP transport
pallavt93 Sep 4, 2026
40e6195
eat: add MCP 2.0 stateless HTTP ingress pipeline and discovery
pallavt93 Sep 4, 2026
6dc4dc4
feat: add MCP 2.0 JSON-RPC wire protocol and error codes
pallavt93 Sep 4, 2026
5984f7b
feat: add MCP 2.0 tool/resource/prompt wire contracts
pallavt93 Sep 4, 2026
9e962f2
feat: implement MCP 2.0 tasks protocol lifecycle and negotiation
pallavt93 Sep 4, 2026
be4cf8a
feat: add pluggable TaskStore with terminal-only TTL eviction
pallavt93 Sep 4, 2026
30dea68
feat: add task authorization and multi-tenant isolation
pallavt93 Sep 4, 2026
2bd87c4
feat: add CIMD resolver with SSRF defenses and RFC 9207 iss validation
pallavt93 Sep 4, 2026
79b0dd5
feat: add MCP 2.0 extensions map, cache hints, and trace context prop…
pallavt93 Sep 4, 2026
58778c6
feat: add MCP 2.0 blueprint conformance registry and verification tests
pallavt93 Sep 4, 2026
93e1402
feat: add PYTHONSDK-11 epic acceptance registry and verification tests
pallavt93 Sep 5, 2026
283d91a
feat: enhance discovery result structure with caching metadata and re…
pallavt93 Sep 5, 2026
0a804fe
reference clean merge
pallavt93 Sep 7, 2026
f5adf8a
added security deps fix
pallavt93 Sep 7, 2026
1b6d9f3
added sync env
pallavt93 Sep 7, 2026
a5ea77e
Merge upstream/develop into feature/stateless_2.0
pallavt93 Sep 8, 2026
9700d46
feat: default MCP protocol era to auto without forcing stateless HTTP
pallavt93 Sep 8, 2026
6b052a1
feat: thread protocol era through HTTP instead of a stateless boolean
pallavt93 Sep 8, 2026
d8c639e
feat: serve 2025 and 2026 clients on one sessionless /mcp
pallavt93 Sep 8, 2026
e270bb0
feat: reject 2025 wire when protocol era is modern
pallavt93 Sep 8, 2026
af58ba1
feat: fall back to ServerConfig protocol era when env is unset
pallavt93 Sep 8, 2026
cb66e92
feat: accept TypeScript protocol era aliases
pallavt93 Sep 8, 2026
1659811
feat: select the HTTP engine from the protocol era
pallavt93 Sep 8, 2026
309f91e
feat: advertise the resolved protocol era on /mcp/health
pallavt93 Sep 8, 2026
65ba22c
feat: serve server/discover from the HTTP engine
pallavt93 Sep 8, 2026
73a339e
feat: answer sessionless initialize on the auto-era engine
pallavt93 Sep 8, 2026
a9be2f6
feat: map request envelope onto execution context without unsigned
pallavt93 Sep 8, 2026
ad30215
feat: resolve handler identity from verified JWT before envelope claims
pallavt93 Sep 8, 2026
15daa12
feat: reject incoming Mcp-Session-Id on sessionless MCP engines
pallavt93 Sep 8, 2026
8972304
feat: drop incoming Mcp-Session-Id before the sessionless HTTP engine
pallavt93 Sep 8, 2026
844deb8
feat: require Mcp-Name on tools/call and reject header mismatches
pallavt93 Sep 8, 2026
ea6b595
feat: require Mcp-Method on modern JSON-RPC POST and tools/call
pallavt93 Sep 8, 2026
41e3b6c
feat: reject protocol version header when it disagrees with the envelope
pallavt93 Sep 8, 2026
83faf59
feat: return -32022 for an unsupported MCP protocol version
pallavt93 Sep 8, 2026
d58d1f7
eat: keep MCP-Protocol-Version through HeaderCompat middleware
pallavt93 Sep 8, 2026
8eb47fc
feat: mirror Mcp-Param headers into missing tool arguments
pallavt93 Sep 8, 2026
c07d931
feat: echo protocol version and method on MCP responses
pallavt93 Sep 8, 2026
cc1f65a
feat: allow 2026 MCP headers on CORS preflight
pallavt93 Sep 8, 2026
e69a4fe
fix: keep OPTIONS 204 scoped to /mcp when CORS is on
pallavt93 Sep 8, 2026
61a1272
feat: expose MCP echo headers on CORS responses
pallavt93 Sep 8, 2026
02233b6
ix: default HTTP bind host to 127.0.0.1
pallavt93 Sep 8, 2026
da7a003
feat: honor forwarded host only from trusted proxies
pallavt93 Sep 8, 2026
157e4c2
feat: answer header-only Mcp-Method ping without a JSON-RPC body
pallavt93 Sep 8, 2026
e40e6bc
feat: apply SEP-2243 header rules from one method contract table
pallavt93 Sep 8, 2026
d823151
feat: pin validated MCP headers on replay and drop session ids
pallavt93 Sep 8, 2026
e34c9c4
feat: answer 2025 initialize on auto without a session
pallavt93 Sep 8, 2026
74519b5
feat: reject 2025 initialize on modern without a session
pallavt93 Sep 8, 2026
880f66f
feat: mount sessionful HTTP only for the legacy era
pallavt93 Sep 8, 2026
a3487f4
feat: serve /mcp with official mcp 2.x
pallavt93 Sep 8, 2026
a4061d5
feat: serve /mcp with official mcp 2.x
pallavt93 Sep 8, 2026
65a7d5d
feat: reject non-2020-12 schemas at tool registration
pallavt93 Sep 8, 2026
dadd0f9
feat: mount /subscriptions/listen on the official v2 bus
pallavt93 Sep 8, 2026
c1774c8
feat: isolate concurrent JSON-RPC calls that reuse the same id
pallavt93 Sep 8, 2026
0a7a4bd
feat: apply deprecated-method policy on every modern route
pallavt93 Sep 8, 2026
e404f17
feat: default unset protocol era to auto
pallavt93 Sep 8, 2026
488839d
feat: strip envelope keys from tool arguments
pallavt93 Sep 8, 2026
12b12f8
feat: serve modern and auto stdio on official mcp 2.x
pallavt93 Sep 8, 2026
5ea3834
feat: fan out task status to listen, SSE, and stdio
pallavt93 Sep 9, 2026
8934ca2
fixed mcp-method-id strict checks issue
pallavt93 Sep 9, 2026
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
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,17 @@ The SDK reads standard settings from the environment or `.env` files:

| Environment Variable | Description |
|---|---|
| `HOST` | Bind address for HTTP/SSE (default: `127.0.0.1`). Set `0.0.0.0` to listen on all interfaces (containers). |
| `TRUSTED_PROXIES` / `MCP_TRUSTED_PROXIES` | Comma-separated IPs, CIDRs, or hostnames allowed to send `X-Forwarded-Host` / `X-Forwarded-Proto`. Unset means those headers are ignored. `X-Forwarded-For` is never used to decide trust. |
| `PORT` / `MCP_SERVER_PORT` | The port to bind for HTTP/SSE transport (default: `3000`). Overridden by `nitrostack-py --port`. |
| `WIDGETS_DEV_PORT` | Widget Next.js port (default: `3001`). Overridden by `nitrostack-py --widget`. |
| `MCP_TRANSPORT_TYPE` | Transport selection: `stdio`, `http`, or `dual` (combining stdio + HTTP/SSE). |
| `NODE_ENV` | If set to `production`, defaults to `dual` transport. Otherwise defaults to `stdio`. |
| `MCP_MAX_SESSIONS` | Cap on concurrent Streamable HTTP sessions; new sessions beyond the cap get an HTTP `429`. Unset = unlimited. |
| `MCP_SESSION_TIMEOUT_MS` | Idle timeout (ms) for stateful HTTP sessions; sessions with no activity for this long are terminated automatically. Unset = no timeout. |
| `MCP_GRACEFUL_SHUTDOWN_TIMEOUT_MS` | How long (ms) the HTTP transport waits for in-flight requests to finish when shutting down (default: `10000`). |
| `MCP_STATELESS` | Set to `true` to run the HTTP transport in stateless mode: every request gets a fresh context with no session id and no `initialize` handshake required. |
| `NITRO_MCP_PROTOCOL_VERSION` | Protocol era (case-insensitive): `auto` / `both` / `dual` / `dual-spec` (default when unset or unknown), `modern` / `latest` / `2026` / `2026-07-28`, or `legacy` / `2025` / `2025-06-18` / `2025-11-25`. `auto` is not the same as `modern`. Wins over `ServerConfig.protocol_era`. |
| `MCP_STATELESS` | Explicit override: `true` forces `modern` (stateless HTTP), `false` forces `legacy` (sessionful). Wins over `NITRO_MCP_PROTOCOL_VERSION` and `ServerConfig.protocol_era`. |
| `MCP_ALLOWED_HOSTS` / `MCP_ALLOWED_ORIGINS` | Comma-separated allow-lists for DNS-rebinding protection, used only when CORS is disabled. |
| `NITROSTACK_LOG_FILE` | Destination file for logs (default: `nitrostack.log`). |
| `NITROSTACK_LOG_LEVEL` | Log level (`DEBUG`, `INFO`, `WARNING`, `ERROR`). |
Expand All @@ -260,6 +263,8 @@ Example:
server = ServerConfig(name="my-server", transport_type="http", max_sessions=100, session_timeout_ms=1_800_000)
```

`ServerConfig.protocol_era` is used only when `MCP_STATELESS` and `NITRO_MCP_PROTOCOL_VERSION` are both unset. Unknown tokens become `auto`, same as an unknown env value.

---

## Developing & Testing
Expand Down
43 changes: 40 additions & 3 deletions nitrostack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@
OAuthService,
generate_www_authenticate_header,
)
from nitrostack.auth.cimd import (
CimdFetchError,
CimdValidationError,
is_blocked_ip,
resolve_cimd,
validate_client_identifier_url,
)
from nitrostack.auth.oauth_security import (
AuthorizationIssuerMismatchError,
validate_authorization_iss,
)
from nitrostack.auth.pkce import (
generate_code_challenge,
generate_code_verifier,
Expand Down Expand Up @@ -118,9 +129,13 @@
from nitrostack.testing import (
NitroTestingModule,
)
from nitrostack.testing import (
NitroTestingModule,
)
from nitrostack.protocol.version import MODERN_PROTOCOL_VERSION
from nitrostack.protocol.errors import JsonRpcErrorCode
from nitrostack.protocol.mrtr import InputRequest, InputRequiredResult, accepted_content, input_required
from nitrostack.tasks import InMemoryTaskStore, TaskAccessContext, TaskStore
from nitrostack.tasks.authorization import check_task_access, extract_task_access_context
from nitrostack.runtime import StatelessInvariants, assert_stateless_headers
from nitrostack.transports import wrap_stateless_transport, StatelessIngressPipeline


__all__ = [
Expand Down Expand Up @@ -165,6 +180,13 @@
"OAuthModule",
"OAuthService",
"generate_www_authenticate_header",
"validate_client_identifier_url",
"resolve_cimd",
"is_blocked_ip",
"CimdValidationError",
"CimdFetchError",
"validate_authorization_iss",
"AuthorizationIssuerMismatchError",
"generate_code_challenge",
"generate_code_verifier",
"generate_pkce_params",
Expand Down Expand Up @@ -207,4 +229,19 @@
"RESOURCE_MIME_TYPE_MCP_APP",
"RESOURCE_MIME_TYPE_OPENAI",
"NitroTestingModule",
"MODERN_PROTOCOL_VERSION",
"JsonRpcErrorCode",
"InputRequest",
"InputRequiredResult",
"accepted_content",
"input_required",
"TaskAccessContext",
"TaskStore",
"InMemoryTaskStore",
"check_task_access",
"extract_task_access_context",
"StatelessInvariants",
"assert_stateless_headers",
"wrap_stateless_transport",
"StatelessIngressPipeline",
]
Loading
Loading