Skip to content

feat(adapters): add mcp_tool_interceptor() to AxonFlowLangGraphAdapter#109

Open
gzak wants to merge 1 commit intomainfrom
feat/langgraph-adapter-mcp-interceptor
Open

feat(adapters): add mcp_tool_interceptor() to AxonFlowLangGraphAdapter#109
gzak wants to merge 1 commit intomainfrom
feat/langgraph-adapter-mcp-interceptor

Conversation

@gzak
Copy link
Contributor

@gzak gzak commented Mar 5, 2026

Summary

Closes #107.

Adds mcp_tool_interceptor() factory method to AxonFlowLangGraphAdapter, returning an async callable ready to pass directly to MultiServerMCPClient:

mcp_client = MultiServerMCPClient(
    {"my-server": {"url": "...", "transport": "http"}},
    tool_interceptors=[adapter.mcp_tool_interceptor()],
)

The method accepts an optional MCPInterceptorOptions object:

opts = MCPInterceptorOptions(
    connector_type_fn=lambda req: req.server_name,
    operation="query",
)
tool_interceptors=[adapter.mcp_tool_interceptor(opts)]

The interceptor enforces AxonFlow input and output policies around every MCP tool call: mcp_check_input → handler() → mcp_check_output.

Design decisions

Redacted output passthrough — when mcp_check_output returns redacted_data, the interceptor substitutes it for the original result rather than discarding it silently:

if output_check.redacted_data is not None:
    return output_check.redacted_data
return result

Pluggable connector type derivationMCPInterceptorOptions.connector_type_fn overrides the default "{server_name}.{tool_name}" mapping for tenants that key connector types differently.

Configurable operation typeMCPInterceptorOptions.operation is forwarded to mcp_check_input (default: "execute"; set to "query" for known read-only tool calls).

No new runtime dependencies

MCPToolCallRequest from langchain-mcp-adapters is only used for type hints under TYPE_CHECKING. The interceptor duck-types request.server_name, request.name, and request.args at runtime.

Test plan

  • 14 new unit tests in tests/test_langgraph_adapter.py:
    • Allowed call returns handler result
    • Default connector type derived as "{server_name}.{tool_name}"
    • Same connector type forwarded to mcp_check_output
    • Default operation is "execute"
    • Custom operation via MCPInterceptorOptions is forwarded
    • Input blocked: raises PolicyViolationError and handler is not called
    • Input blocked with no reason: fallback message used
    • Output blocked: raises PolicyViolationError
    • Output blocked with no reason: fallback message used
    • Redacted output returned in place of original result
    • Original result returned when no redaction
    • Custom connector_type_fn used for both input and output checks
    • Each factory call returns an independent interceptor
  • MCPInterceptorOptions and WorkflowApprovalRequiredError exported from axonflow.adapters
  • CHANGELOG.md updated with 3.8.0 entry
  • Full existing test suite passes (592 tests)

@gzak gzak force-pushed the feat/langgraph-adapter-mcp-interceptor branch 5 times, most recently from 4d0425f to d61af71 Compare March 6, 2026 00:39
Adds a factory method that returns an async MCP tool interceptor ready
for use with MultiServerMCPClient(tool_interceptors=[...]).

The interceptor enforces AxonFlow input and output policies around every
MCP tool call: mcp_check_input → handler() → mcp_check_output. Two
design decisions incorporated:

- Redacted output passthrough: when mcp_check_output returns redacted_data,
  the interceptor substitutes it for the original result rather than
  discarding it silently.
- Pluggable connector type derivation: accepts an optional connector_type_fn
  callable to override the default "{server_name}.{tool_name}" mapping,
  allowing callers to match their AxonFlow policy connector type keys.

Closes #107

feat: add mcp_check_input and mcp_check_output methods (#103)
@gzak gzak force-pushed the feat/langgraph-adapter-mcp-interceptor branch from d61af71 to fad1539 Compare March 6, 2026 00:42
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.

feat(adapters): add mcp_tool_interceptor() factory to AxonFlowLangGraphAdapter

1 participant