Skip to content

feat(mcp-server): implement all 19 MCP 2026-07-28 SEPs - #75

Open
pratistha19 wants to merge 9 commits into
redhat-data-and-ai:deep-agentfrom
pratistha19:feat/new-sep-updates
Open

feat(mcp-server): implement all 19 MCP 2026-07-28 SEPs#75
pratistha19 wants to merge 9 commits into
redhat-data-and-ai:deep-agentfrom
pratistha19:feat/new-sep-updates

Conversation

@pratistha19

@pratistha19 pratistha19 commented Jul 21, 2026

Copy link
Copy Markdown

Description

Implements all 19 SEPs from the MCP 2026-07-28 specification, removes SSE transport, adds stdio transport, adds ToolAnnotations on all tools, and brings test coverage to 741 tests at 100% across 29 source files (1885 statements, 0 missed).


SEP Implementations

Transport & Protocol

  • SEP-2567 (Session removal): Server runs in stateless HTTP mode — no Mcp-Session-Id header, no session tracking, no Last-Event-ID resumability. stateless_http=True by default, configurable via MCP_STATELESS_HTTP.
  • SEP-2575 (Stateless MCP): server/discover replaces the initialize handshake. Removed methods (ping, logging/setLevel, notifications/roots/list_changed, tasks/list) return -32023 METHOD_NOT_SUPPORTED. Per-request _meta.logLevel replaces stateful logging config.
  • SEP-2322 (Multi Round-Trip Requests): Full end-to-end MRTR implementation. New mrtr.py module (23 stmts) with InputRequest model, input_required_result() / complete_result() builders, and get_response_value() lookup. Middleware intercepts MRTR-enabled tools (e.g., send_email) — first call returns resultType: "input_required" with inputRequests asking for confirmation; client retries with inputResponses; confirmed calls execute the tool and return resultType: "complete". Non-MRTR tools still get resultType: "complete" injected via _inject_result_type(). server/discover advertises multiRoundTrip: true in tools capability. Configurable via MCP_MRTR_ENABLED.
  • SEP-2260 (Server request association): No standalone server-to-client pushes. Verified structurally — tools-first architecture (no resources, no prompts, no subscriptions).

Observability

  • SEP-414 (W3C Trace Context): New tracing.py module (60 stmts) — parses traceparent/tracestate/baggage from HTTP headers and MCP _meta fields, generates server span IDs, injects trace_id/span_id into structlog via contextvars. Middleware binds trace context per request and returns traceparent in response headers.

OAuth & Security

  • SEP-837 (application_type in DCR): _infer_application_type() classifies redirect URIs — loopback/custom-scheme → "native", HTTPS → "web". Stored in oauth_clients table and returned in registration response.
  • SEP-991 / PR-2858 (CIMD + DCR deprecation): GET /auth/client-metadata/{client_id} serves read-only client metadata. POST /auth/register returns Deprecation: true header. Well-known metadata advertises registration_endpoint_is_deprecated: true.
  • SEP-2207 (OIDC refresh token guidance): SCOPES_SUPPORTED excludes offline_access with a module-level validation guard. Refresh tokens controlled via grant_types_supported.
  • SEP-2352 (Client credential binding): All OAuth artifacts bound to issuer. OAuthService takes issuer param; auth code and refresh token grant handlers reject tokens from different issuers. PRIMARY KEY (issuer, client_id).
  • SEP-2468 (iss in auth responses): handle_callback() includes iss in redirect params (RFC 9207). AS metadata returns authorization_response_iss_parameter_supported: true.

Schema & Tools

  • SEP-2106 (JSON Schema 2020-12): New schema.py module (60 stmts) — validates inputSchema (root type: "object"), outputSchema, and $ref resolution within $defs. All 4 tools define OUTPUT_SCHEMA with structuredContent.

  • SEP-2549 (Deterministic tools/list + cache metadata): _ensure_deterministic_tool_order() sorts tools by name for client-side caching and LLM prompt cache hits. TOOL_CACHE_TTL_MS and TOOL_CACHE_SCOPE configurable.

  • SEP-2243 (Mcp-Method / Mcp-Name header validation): Middleware validates headers match JSON-RPC body. Returns -32020 HEADER_MISMATCH on mismatch. Response includes x-mcp-method and x-mcp-name.

  • Tool Annotations: All 4 tools registered with ToolAnnotations behavioral hints via mcp.tool(annotations=...):

    Tool title readOnlyHint destructiveHint idempotentHint openWorldHint
    calculate_bmi BMI Calculator true false true false
    search_web Web Search true false true true
    send_email Send Email false true false true
    validate_email Validate Email true false true false

Extensions

  • SEP-2133 (Extensions framework): New extensions.py (20 stmts) — ExtensionRegistry with reverse-DNS identifiers. Capabilities advertised in server/discover.
  • SEP-1865 (MCP Apps): New apps.py (35 stmts) — AppRegistry with register/unregister/get/list. RPC handlers: apps/list, apps/get. Default "health-dashboard" app registered.
  • SEP-2663 (Tasks): New tasks.py (73 stmts) — TaskStore with full lifecycle (pendingrunningcompleted/failed/cancelled). RPC handlers: tasks/get, tasks/update, tasks/cancel. Progress clamped to [0,1], terminal tasks reject updates.

Deprecation & Lifecycle

  • SEP-2577 (Deprecate roots, sampling, logging): Pre-registers deprecation entries with migration guidance in server/discover (roots → tool params, sampling → direct LLM APIs, logging → per-request _meta.logLevel).
  • SEP-2596 (Feature lifecycle policy): New deprecation.py (43 stmts) — DeprecationRegistry with active/deprecated/removed states. 15 entries pre-registered from the 2026-07-28 spec.

Error Codes

  • Error codes (allocation + renumbering): New errors.py (27 stmts) — code ranges per spec (-32000 to -32019 implementation-defined, -32020 to -32099 MCP-reserved). HeaderMismatchError (-32020), MethodNotSupportedError (-32023), ResourceNotFoundError (-32602).

Transport Changes

  • Removed SSE transport branch from api.py — Streamable HTTP is now the only HTTP transport
  • Added stdio transport in main.py using FastMCP.run_stdio_async() with lazy imports
  • Default transport changed from "http" to "streamable-http" in settings

Hardcoded Value Removal

  • handler.py: SSO scopes and introspection timeout from settings.SSO_SCOPES / settings.SSO_INTROSPECTION_TIMEOUT
  • email_tool.py: RESEND_FROM_EMAIL now required (no hardcoded fallback)
  • settings.py: Added OAUTH_ISSUER, ACCESS_TOKEN_EXPIRY, SESSION_COOKIE_HTTPS_ONLY, SESSION_COOKIE_SAME_SITE, SESSION_COOKIE_MAX_AGE, SSO_SCOPES, SSO_INTROSPECTION_TIMEOUT, MCP_TRACE_CONTEXT_ENABLED, MCP_EXTENSIONS_ENABLED, MCP_STATELESS_HTTP, MCP_PROTOCOL_VERSION, TOOL_CACHE_TTL_MS, TOOL_CACHE_SCOPE, MCP_MRTR_ENABLED

Dead Code Removal

  • service.py: Removed 14 backward-compat wrapper functions
  • models.py: Removed 5 unused Pydantic models
  • conftest.py: Removed 11 unused test fixtures
  • test_utils.py: Removed 3 duplicate test cases
  • test_oauth_controller.py: Removed placeholder test class

Code Reuse

  • controller.py: Extracted _validate_client_credentials() helper (3 duplicated blocks → 1)
  • api.py: get_host() checks OAUTH_ISSUER first, matching get_current_issuer() logic
  • pylogger.py: Added structlog.contextvars.merge_contextvars for trace context propagation

Breaking Changes

  • OAuthService.__init__() requires issuer parameter
  • storage_service.get_client() / get_client_by_name_and_redirect_uris() require issuer parameter
  • 14 backward-compat wrapper functions removed from service.py
  • RESEND_FROM_EMAIL now required (no hardcoded fallback)
  • SSO_SCOPES default changed to ["email", "openid", "profile"] (configurable)

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)
  • CI/CD or infrastructure change
  • Dependency update

Checklist

  • My code follows the project's coding standards (Ruff, MyPy, pydocstyle)
  • I have added tests that prove my fix is effective or my feature works
  • All new and existing tests pass (make test)
  • Pre-commit hooks pass (make pre-commit)
  • Code coverage remains >= 80% (make coverage)
  • I have updated documentation where necessary
  • I have updated CHANGELOG.md (if applicable)
  • My PR title follows Conventional Commits format

Testing

741 tests passing, 100% coverage across 29 source files (1885 statements, 0 missed).

Key test coverage by SEP:

SEP Test Files Tests What's Verified
SEP-414 test_tracing.py, test_api.py 37 traceparent parsing, span generation, MCP _meta extraction, header propagation, structlog injection
SEP-837 test_oauth_service.py, test_oauth_controller.py 8 native/web inference for all URI patterns, explicit override, storage persistence
SEP-991 test_oauth_routes.py, test_api.py 12 CIMD endpoint, DCR deprecation header, well-known metadata
SEP-2106 test_schema.py, test_mcp.py 45 inputSchema/outputSchema validation, $ref resolution, 2020-12 dialect, structured content
SEP-2133 test_extensions.py, test_api.py 14 Registry CRUD, capabilities in server/discover
SEP-2207 test_api.py 3 offline_access exclusion, scopes_supported, grant_types_supported
SEP-2243 test_api.py 6 Header match/mismatch, response headers, -32020 error
SEP-2260 test_api.py 2 No resource/prompt/subscription in components
SEP-2322 test_mrtr.py, test_api.py 29 MRTR module (InputRequest, get_response_value, result builders), end-to-end flow (input_required → inputResponses → confirmed/cancelled/error), trace headers, disabled bypass
SEP-2352 test_oauth_service.py, test_oauth_controller.py, test_storage_service.py 15 Issuer binding, cross-issuer rejection, PK constraint
SEP-2468 test_oauth_controller.py, test_api.py 4 iss in redirect, metadata flag
SEP-2549 test_mcp.py 5 Deterministic ordering, cache metadata
SEP-2567 test_settings.py, test_api.py 4 Stateless HTTP config, no session header
SEP-2575 test_api.py 8 server/discover, removed methods -32023, _meta.logLevel
SEP-2577 test_deprecation.py, test_api.py 10 Migration guidance, server/discover entries
SEP-2596 test_deprecation.py 12 Lifecycle states, registry serialization, 15 entries
SEP-1865 test_apps.py, test_api.py 19 AppRegistry CRUD, apps/list, apps/get, RESOURCE_NOT_FOUND
SEP-2663 test_tasks.py, test_api.py 34 TaskStore lifecycle, progress clamping, terminal rejection, RPC handlers
Error codes test_errors.py 14 Exception classes, code ranges, ErrorData
Tool Annotations test_mcp.py 5 All 4 tools have ToolAnnotations, per-tool hint verification (readOnly, destructive, idempotent, openWorld, title)

Pratistha Singh and others added 2 commits July 23, 2026 12:04
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Pratistha Singh <pratisin@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Pratistha Singh <pratisin@redhat.com>
@pratistha19
pratistha19 force-pushed the feat/new-sep-updates branch from 375ecb3 to fb9ae6b Compare July 23, 2026 06:35
Signed-off-by: Pratistha Singh <pratisin@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 68035ccc-8ab5-45df-9d2f-adeb4ebff69d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pratistha19 pratistha19 changed the title feat(mcp-server): add DCR OAuth integration and documentation updates feat(mcp-server): add stdio transport, OAuth hardening (iss + application_type), and remove SSE Jul 29, 2026

def _get_issuer() -> str:
safe_default = "http://localhost:5001"
endpoint = getattr(settings, "MCP_HOST_ENDPOINT", None) or safe_default

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not defined in the settings.

@NP-compete NP-compete left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we create atomic PRs?

Signed-off-by: Pratistha Singh <pratisin@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@pratistha19 pratistha19 changed the title feat(mcp-server): add stdio transport, OAuth hardening (iss + application_type), and remove SSE feat(mcp-server): implement MCP 2026-07-28 SEPs, remove SSE, add stdio transport Aug 7, 2026
…d test coverage

Signed-off-by: Pratistha Singh <pratisin@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@pratistha19
pratistha19 force-pushed the feat/new-sep-updates branch from b3eca3d to e40c0a4 Compare August 11, 2026 05:54
@pratistha19 pratistha19 changed the title feat(mcp-server): implement MCP 2026-07-28 SEPs, remove SSE, add stdio transport feat(mcp-server): implement all 19 MCP 2026-07-28 SEPs with 100% test coverage Aug 11, 2026
Pratistha Singh and others added 3 commits August 11, 2026 11:51
Signed-off-by: Pratistha Singh <pratisin@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Pratistha Singh <pratisin@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Pratistha Singh <pratisin@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@pratistha19 pratistha19 changed the title feat(mcp-server): implement all 19 MCP 2026-07-28 SEPs with 100% test coverage feat(mcp-server): implement all 19 MCP 2026-07-28 SEPs Aug 11, 2026
Signed-off-by: Pratistha Singh <pratisin@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants