context-compiler-example-integrations 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. context_compiler_example_integrations/README.md +71 -0
  2. context_compiler_example_integrations/__init__.py +1 -0
  3. context_compiler_example_integrations/examples/__init__.py +12 -0
  4. context_compiler_example_integrations/examples/_shared/__init__.py +1 -0
  5. context_compiler_example_integrations/examples/_shared/litellm_request.py +61 -0
  6. context_compiler_example_integrations/examples/_shared/provider_mode.py +91 -0
  7. context_compiler_example_integrations/examples/checkpoint_continuation/README.md +77 -0
  8. context_compiler_example_integrations/examples/checkpoint_continuation/example.py +169 -0
  9. context_compiler_example_integrations/examples/checkpoint_continuation/fastapi/README.md +85 -0
  10. context_compiler_example_integrations/examples/checkpoint_continuation/fastapi/app.py +205 -0
  11. context_compiler_example_integrations/examples/execution_authorization/README.md +31 -0
  12. context_compiler_example_integrations/examples/execution_authorization/expense_approval/README.md +77 -0
  13. context_compiler_example_integrations/examples/execution_authorization/expense_approval/__init__.py +1 -0
  14. context_compiler_example_integrations/examples/execution_authorization/expense_approval/example.py +168 -0
  15. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/README.md +97 -0
  16. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/__init__.py +1 -0
  17. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/app.py +312 -0
  18. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/model_approval.py +98 -0
  19. context_compiler_example_integrations/examples/gateway_middleware/README.md +49 -0
  20. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/README.md +40 -0
  21. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/__init__.py +1 -0
  22. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/example.py +220 -0
  23. context_compiler_example_integrations/examples/prompt_construction/README.md +27 -0
  24. context_compiler_example_integrations/examples/prompt_construction/litellm/README.md +197 -0
  25. context_compiler_example_integrations/examples/prompt_construction/litellm/basic.py +392 -0
  26. context_compiler_example_integrations/examples/prompt_construction/litellm/confirmation_helper.py +91 -0
  27. context_compiler_example_integrations/examples/prompt_construction/litellm/with_directive_drafter.py +524 -0
  28. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/README.md +92 -0
  29. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/__init__.py +1 -0
  30. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/example.py +205 -0
  31. context_compiler_example_integrations/examples/retrieval_filtering/README.md +65 -0
  32. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/README.md +120 -0
  33. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/__init__.py +1 -0
  34. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/example.py +320 -0
  35. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/README.md +123 -0
  36. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/__init__.py +1 -0
  37. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/example.py +300 -0
  38. context_compiler_example_integrations/examples/schema_selection/README.md +41 -0
  39. context_compiler_example_integrations/examples/schema_selection/litellm_response_format/response_format.py +218 -0
  40. context_compiler_example_integrations/examples/schema_selection/ollama_structured_output/README.md +60 -0
  41. context_compiler_example_integrations/examples/schema_selection/ollama_structured_output/example.py +171 -0
  42. context_compiler_example_integrations/examples/schema_selection/refund_intake/README.md +95 -0
  43. context_compiler_example_integrations/examples/schema_selection/refund_intake/__init__.py +1 -0
  44. context_compiler_example_integrations/examples/schema_selection/refund_intake/example.py +180 -0
  45. context_compiler_example_integrations/examples/tool_gating/README.md +55 -0
  46. context_compiler_example_integrations/examples/tool_gating/calendar_admin/README.md +34 -0
  47. context_compiler_example_integrations/examples/tool_gating/calendar_admin/__init__.py +1 -0
  48. context_compiler_example_integrations/examples/tool_gating/calendar_admin/example.py +195 -0
  49. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/README.md +93 -0
  50. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/__init__.py +1 -0
  51. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/example.py +250 -0
  52. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/live_model.py +369 -0
  53. context_compiler_example_integrations/reference_integrations/__init__.py +12 -0
  54. context_compiler_example_integrations/reference_integrations/litellm_proxy/README.md +251 -0
  55. context_compiler_example_integrations/reference_integrations/litellm_proxy/_checkpoint_support.py +146 -0
  56. context_compiler_example_integrations/reference_integrations/litellm_proxy/config.example.yaml +23 -0
  57. context_compiler_example_integrations/reference_integrations/litellm_proxy/context_compiler_precall_hook.py +163 -0
  58. context_compiler_example_integrations/reference_integrations/litellm_proxy/context_compiler_precall_hook_with_directive_drafter.py +289 -0
  59. context_compiler_example_integrations/reference_integrations/openwebui_pipe/README.md +233 -0
  60. context_compiler_example_integrations/reference_integrations/openwebui_pipe/open_webui_pipe.py +750 -0
  61. context_compiler_example_integrations/reference_integrations/openwebui_pipe/open_webui_pipe_with_directive_drafter.py +1045 -0
  62. context_compiler_example_integrations-0.1.0.dist-info/METADATA +110 -0
  63. context_compiler_example_integrations-0.1.0.dist-info/RECORD +65 -0
  64. context_compiler_example_integrations-0.1.0.dist-info/WHEEL +4 -0
  65. context_compiler_example_integrations-0.1.0.dist-info/licenses/LICENSE +173 -0
@@ -0,0 +1,195 @@
1
+ """Host-side tool gating using authoritative Context Compiler state."""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Literal, TypedDict, cast
5
+
6
+ from context_compiler import (
7
+ POLICY_PROHIBIT,
8
+ POLICY_USE,
9
+ State,
10
+ create_engine,
11
+ get_decision_state,
12
+ get_policy_items,
13
+ is_clarify,
14
+ )
15
+ from context_compiler.engine import Engine
16
+
17
+
18
+ class CalendarToolCall(TypedDict):
19
+ tool_name: str
20
+ calendar_id: str
21
+ event_title: str
22
+
23
+
24
+ class ToolRegistrySnapshot(TypedDict):
25
+ available_tools: list[str]
26
+ hidden_tools: list[str]
27
+
28
+
29
+ class CalendarToolExecutionResult(TypedDict):
30
+ authorization_state: Literal["allowed", "blocked"]
31
+ tool_visible: bool
32
+ executed: bool
33
+ blocked_reason: str | None
34
+ tool_result: str | None
35
+ registry_snapshot: ToolRegistrySnapshot
36
+ execution_log: list[str]
37
+
38
+
39
+ class CalendarToolTurnResult(TypedDict):
40
+ decision_kind: Literal["clarify", "update", "passthrough"]
41
+ prompt_to_user: str | None
42
+ execution_result: CalendarToolExecutionResult
43
+
44
+
45
+ def _decision_kind_name(
46
+ decision: object,
47
+ ) -> Literal["clarify", "update", "passthrough"]:
48
+ if not isinstance(decision, dict):
49
+ raise ValueError("unexpected decision shape")
50
+
51
+ kind = decision.get("kind")
52
+ kind_name = getattr(kind, "value", None)
53
+ if kind_name not in {"clarify", "update", "passthrough"}:
54
+ raise ValueError(f"unexpected decision kind: {kind_name}")
55
+
56
+ return cast(Literal["clarify", "update", "passthrough"], kind_name)
57
+
58
+
59
+ @dataclass
60
+ class CalendarAdminHost:
61
+ """Host-owned tool registry and execution layer."""
62
+
63
+ execution_log: list[str]
64
+
65
+ def __init__(self) -> None:
66
+ self.execution_log = []
67
+ self._always_available_tools = ["calendar_view_events"]
68
+ self._calendar_admin_tools = ["calendar_admin_create_event"]
69
+
70
+ def visible_tools(self, state: State) -> ToolRegistrySnapshot:
71
+ available_tools = self._always_available_tools.copy()
72
+ hidden_tools = self._calendar_admin_tools.copy()
73
+
74
+ if calendar_admin_tools_are_allowed(state):
75
+ available_tools.extend(self._calendar_admin_tools)
76
+ hidden_tools = []
77
+
78
+ return {
79
+ "available_tools": available_tools,
80
+ "hidden_tools": hidden_tools,
81
+ }
82
+
83
+ def execute_calendar_admin_tool(self, tool_call: CalendarToolCall) -> str:
84
+ self.execution_log.append(
85
+ f"{tool_call['tool_name']}:{tool_call['calendar_id']}:{tool_call['event_title']}"
86
+ )
87
+ return (
88
+ f"created event '{tool_call['event_title']}' "
89
+ f"on calendar '{tool_call['calendar_id']}'"
90
+ )
91
+
92
+
93
+ def calendar_admin_tools_are_allowed(state: State) -> bool:
94
+ """Allow calendar admin tools only from authoritative compiler state."""
95
+
96
+ use_items = set(get_policy_items(state, POLICY_USE))
97
+ prohibit_items = set(get_policy_items(state, POLICY_PROHIBIT))
98
+
99
+ if "calendar_admin" in prohibit_items:
100
+ return False
101
+
102
+ return "calendar_admin" in use_items
103
+
104
+
105
+ def execute_calendar_admin_tool_if_allowed(
106
+ tool_call: CalendarToolCall,
107
+ *,
108
+ state: State,
109
+ host: CalendarAdminHost,
110
+ ) -> CalendarToolExecutionResult:
111
+ """Hide or execute the admin tool based only on authoritative state."""
112
+
113
+ registry_snapshot = host.visible_tools(state)
114
+ tool_visible = tool_call["tool_name"] in registry_snapshot["available_tools"]
115
+
116
+ if not tool_visible:
117
+ return {
118
+ "authorization_state": "blocked",
119
+ "tool_visible": False,
120
+ "executed": False,
121
+ "blocked_reason": "calendar_admin state not authorized",
122
+ "tool_result": None,
123
+ "registry_snapshot": registry_snapshot,
124
+ "execution_log": host.execution_log.copy(),
125
+ }
126
+
127
+ tool_result = host.execute_calendar_admin_tool(tool_call)
128
+ return {
129
+ "authorization_state": "allowed",
130
+ "tool_visible": True,
131
+ "executed": True,
132
+ "blocked_reason": None,
133
+ "tool_result": tool_result,
134
+ "registry_snapshot": registry_snapshot,
135
+ "execution_log": host.execution_log.copy(),
136
+ }
137
+
138
+
139
+ def handle_calendar_admin_turn(
140
+ engine: Engine,
141
+ *,
142
+ compiler_input: str,
143
+ tool_call: CalendarToolCall,
144
+ host: CalendarAdminHost,
145
+ ) -> CalendarToolTurnResult:
146
+ """Block tool exposure on clarify and otherwise enforce current state."""
147
+
148
+ decision = engine.step(compiler_input)
149
+
150
+ if is_clarify(decision):
151
+ return {
152
+ "decision_kind": "clarify",
153
+ "prompt_to_user": decision.get("prompt_to_user"),
154
+ "execution_result": {
155
+ "authorization_state": "blocked",
156
+ "tool_visible": False,
157
+ "executed": False,
158
+ "blocked_reason": "clarification required before exposing calendar admin tools",
159
+ "tool_result": None,
160
+ "registry_snapshot": host.visible_tools(engine.state),
161
+ "execution_log": host.execution_log.copy(),
162
+ },
163
+ }
164
+
165
+ authoritative_state = get_decision_state(decision)
166
+ if authoritative_state is None:
167
+ authoritative_state = engine.state
168
+
169
+ return {
170
+ "decision_kind": _decision_kind_name(decision),
171
+ "prompt_to_user": decision.get("prompt_to_user"),
172
+ "execution_result": execute_calendar_admin_tool_if_allowed(
173
+ tool_call,
174
+ state=authoritative_state,
175
+ host=host,
176
+ ),
177
+ }
178
+
179
+
180
+ def run_demo() -> CalendarToolExecutionResult:
181
+ """Run a deterministic demonstration with explicit authorization state."""
182
+
183
+ engine = create_engine()
184
+ engine.step("use calendar_admin")
185
+ host = CalendarAdminHost()
186
+
187
+ return execute_calendar_admin_tool_if_allowed(
188
+ {
189
+ "tool_name": "calendar_admin_create_event",
190
+ "calendar_id": "ops-admin",
191
+ "event_title": "Quarterly access review",
192
+ },
193
+ state=engine.state,
194
+ host=host,
195
+ )
@@ -0,0 +1,93 @@
1
+ # `mcp_calendar_admin`
2
+
3
+ Authoritative state changes whether the host exposes and executes the calendar
4
+ admin MCP tool. This example shows tool gating with MCP as the integration
5
+ surface.
6
+
7
+ Context Compiler owns the authoritative policy state that decides whether the
8
+ host exposes the calendar admin MCP tool.
9
+
10
+ The host exposes and allows `calendar_admin_create_event` only when state
11
+ contains:
12
+
13
+ ```text
14
+ use calendar_admin
15
+ ```
16
+
17
+ The host omits that tool from the exposed MCP tool set when state is absent or
18
+ when state contains:
19
+
20
+ ```text
21
+ prohibit calendar_admin
22
+ ```
23
+
24
+ If a caller still invokes the hidden tool directly, the host blocks execution.
25
+
26
+ Adversarial request text does not expose the tool or mutate policy state.
27
+
28
+ The provider-free tests are the canonical proof for this example.
29
+
30
+ This example also includes an opt-in live-model comparison that shows the same
31
+ admin-calendar intent reaches different outcomes because authoritative Context
32
+ Compiler state changes the model-visible tool surface.
33
+
34
+ ## Live-model comparison
35
+
36
+ The live-model path keeps the same host-owned MCP tool registry and execution
37
+ rules.
38
+
39
+ The host exposes only the MCP tools allowed by authoritative state, then asks a
40
+ real tool-calling model to complete the same admin action.
41
+
42
+ The model can only use the tools the host exposes.
43
+
44
+ This is not prompt reinjection:
45
+
46
+ - the host does not derive authority from model output
47
+ - the model does not create or mutate authoritative state
48
+ - Context Compiler state determines whether the protected admin tool is visible
49
+ and executable
50
+
51
+ ### Same request, different state
52
+
53
+ User intent:
54
+
55
+ ```text
56
+ Create an admin calendar event named Quarterly access review on calendar ops-admin.
57
+ ```
58
+
59
+ Outcome matrix:
60
+
61
+ - absent state: protected tool is not exposed, and no protected side effect
62
+ occurs
63
+ - `use calendar_admin`: protected tool is exposed; if the model selects it, the
64
+ host executes it and writes one side effect
65
+ - contradiction with `prohibit calendar_admin`: Context Compiler returns
66
+ clarify/conflict and blocks protected execution before tool execution
67
+
68
+ ### Validation
69
+
70
+ Canonical provider-free tests:
71
+
72
+ ```bash
73
+ uv run --no-sync pytest python/tests/test_mcp_calendar_admin_tool_gating_example.py
74
+ uv run --no-sync pytest python/tests/test_mcp_calendar_admin_live_model_helper.py
75
+ ```
76
+
77
+ Opt-in live-model validation:
78
+
79
+ ```bash
80
+ export RUN_MCP_CALENDAR_ADMIN_LIVE_MODEL=1
81
+ export MODEL=openai/gpt-4o-mini
82
+ export OPENAI_API_KEY=...
83
+ uv run --no-sync pytest python/tests/test_mcp_calendar_admin_live_model.py
84
+ ```
85
+
86
+ This live-model path uses the shared provider contract documented in
87
+ [PROVIDER_CONTRACT.md](../../../../PROVIDER_CONTRACT.md).
88
+
89
+ Example-specific note for local Ollama:
90
+
91
+ - this example accepts either `PROVIDER=ollama` with a bare `MODEL` such as
92
+ `qwen2.5:1.5b-instruct`
93
+ - or an explicit LiteLLM-style `MODEL=ollama/qwen2.5:1.5b-instruct`
@@ -0,0 +1 @@
1
+ """MCP calendar admin tool-gating example."""
@@ -0,0 +1,250 @@
1
+ """MCP-surface tool gating using authoritative Context Compiler state."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Literal, NotRequired, TypedDict, cast
5
+
6
+ from context_compiler import (
7
+ POLICY_PROHIBIT,
8
+ POLICY_USE,
9
+ State,
10
+ create_engine,
11
+ get_decision_state,
12
+ get_policy_items,
13
+ is_clarify,
14
+ )
15
+ from context_compiler.engine import Engine
16
+
17
+
18
+ class McpToolDefinition(TypedDict):
19
+ name: str
20
+ title: str
21
+ description: str
22
+
23
+
24
+ class McpToolCall(TypedDict):
25
+ tool_name: str
26
+ arguments: dict[str, str]
27
+
28
+
29
+ class ExposedMcpTools(TypedDict):
30
+ tools: list[McpToolDefinition]
31
+ hidden_tool_names: list[str]
32
+
33
+
34
+ class McpToolExecutionResult(TypedDict):
35
+ authorization_state: Literal["allowed", "blocked"]
36
+ tool_visible: bool
37
+ executed: bool
38
+ blocked_reason: str | None
39
+ tool_result: str | None
40
+ exposed_tools: ExposedMcpTools
41
+ execution_log: list[str]
42
+
43
+
44
+ class McpToolTurnResult(TypedDict):
45
+ decision_kind: Literal["clarify", "update", "passthrough"]
46
+ prompt_to_user: str | None
47
+ execution_result: McpToolExecutionResult
48
+
49
+
50
+ class McpDecisionResult(TypedDict):
51
+ decision_kind: Literal["clarify", "update", "passthrough"]
52
+ prompt_to_user: str | None
53
+ exposed_tools: ExposedMcpTools
54
+ execution_result: NotRequired[McpToolExecutionResult]
55
+
56
+
57
+ def _decision_kind_name(
58
+ decision: object,
59
+ ) -> Literal["clarify", "update", "passthrough"]:
60
+ if not isinstance(decision, dict):
61
+ raise ValueError("unexpected decision shape")
62
+
63
+ kind = decision.get("kind")
64
+ kind_name = getattr(kind, "value", None)
65
+ if kind_name not in {"clarify", "update", "passthrough"}:
66
+ raise ValueError(f"unexpected decision kind: {kind_name}")
67
+
68
+ return cast(Literal["clarify", "update", "passthrough"], kind_name)
69
+
70
+
71
+ @dataclass
72
+ class CalendarAdminMcpHost:
73
+ """Host-owned MCP registry and execution layer."""
74
+
75
+ execution_log: list[str] = field(default_factory=list)
76
+ _always_available_tools: list[McpToolDefinition] = field(
77
+ default_factory=lambda: [
78
+ {
79
+ "name": "calendar_view_events",
80
+ "title": "View calendar events",
81
+ "description": "List visible events from a calendar.",
82
+ }
83
+ ]
84
+ )
85
+ _calendar_admin_tools: list[McpToolDefinition] = field(
86
+ default_factory=lambda: [
87
+ {
88
+ "name": "calendar_admin_create_event",
89
+ "title": "Create calendar event",
90
+ "description": "Create an administrative event on a calendar.",
91
+ }
92
+ ]
93
+ )
94
+
95
+ def exposed_mcp_tools(self, state: State) -> ExposedMcpTools:
96
+ tools = self._always_available_tools.copy()
97
+ hidden_tool_names = [tool["name"] for tool in self._calendar_admin_tools]
98
+
99
+ if calendar_admin_mcp_tools_are_allowed(state):
100
+ tools.extend(self._calendar_admin_tools)
101
+ hidden_tool_names = []
102
+
103
+ return {
104
+ "tools": tools,
105
+ "hidden_tool_names": hidden_tool_names,
106
+ }
107
+
108
+ def execute_mcp_tool(self, tool_call: McpToolCall) -> str:
109
+ calendar_id = tool_call["arguments"]["calendar_id"]
110
+ event_title = tool_call["arguments"]["event_title"]
111
+ self.execution_log.append(
112
+ f"{tool_call['tool_name']}:{calendar_id}:{event_title}"
113
+ )
114
+ return f"created event '{event_title}' on calendar '{calendar_id}'"
115
+
116
+
117
+ def calendar_admin_mcp_tools_are_allowed(state: State) -> bool:
118
+ """Allow admin MCP tools only from authoritative compiler state."""
119
+
120
+ use_items = set(get_policy_items(state, POLICY_USE))
121
+ prohibit_items = set(get_policy_items(state, POLICY_PROHIBIT))
122
+
123
+ if "calendar_admin" in prohibit_items:
124
+ return False
125
+
126
+ return "calendar_admin" in use_items
127
+
128
+
129
+ def execute_mcp_tool_if_allowed(
130
+ tool_call: McpToolCall,
131
+ *,
132
+ state: State,
133
+ host: CalendarAdminMcpHost,
134
+ ) -> McpToolExecutionResult:
135
+ """Expose and execute MCP tools only when authoritative state allows them."""
136
+
137
+ exposed_tools = host.exposed_mcp_tools(state)
138
+ visible_tool_names = [tool["name"] for tool in exposed_tools["tools"]]
139
+ tool_visible = tool_call["tool_name"] in visible_tool_names
140
+
141
+ if not tool_visible:
142
+ return {
143
+ "authorization_state": "blocked",
144
+ "tool_visible": False,
145
+ "executed": False,
146
+ "blocked_reason": "calendar_admin state not authorized",
147
+ "tool_result": None,
148
+ "exposed_tools": exposed_tools,
149
+ "execution_log": host.execution_log.copy(),
150
+ }
151
+
152
+ tool_result = host.execute_mcp_tool(tool_call)
153
+ return {
154
+ "authorization_state": "allowed",
155
+ "tool_visible": True,
156
+ "executed": True,
157
+ "blocked_reason": None,
158
+ "tool_result": tool_result,
159
+ "exposed_tools": exposed_tools,
160
+ "execution_log": host.execution_log.copy(),
161
+ }
162
+
163
+
164
+ def handle_mcp_tool_turn(
165
+ engine: Engine,
166
+ *,
167
+ compiler_input: str,
168
+ tool_call: McpToolCall,
169
+ host: CalendarAdminMcpHost,
170
+ ) -> McpToolTurnResult:
171
+ """Block MCP tool exposure on clarify and otherwise enforce current state."""
172
+
173
+ decision = engine.step(compiler_input)
174
+
175
+ if is_clarify(decision):
176
+ return {
177
+ "decision_kind": "clarify",
178
+ "prompt_to_user": decision.get("prompt_to_user"),
179
+ "execution_result": {
180
+ "authorization_state": "blocked",
181
+ "tool_visible": False,
182
+ "executed": False,
183
+ "blocked_reason": "clarification required before exposing calendar admin MCP tools",
184
+ "tool_result": None,
185
+ "exposed_tools": host.exposed_mcp_tools(engine.state),
186
+ "execution_log": host.execution_log.copy(),
187
+ },
188
+ }
189
+
190
+ authoritative_state = get_decision_state(decision)
191
+ if authoritative_state is None:
192
+ authoritative_state = engine.state
193
+
194
+ return {
195
+ "decision_kind": _decision_kind_name(decision),
196
+ "prompt_to_user": decision.get("prompt_to_user"),
197
+ "execution_result": execute_mcp_tool_if_allowed(
198
+ tool_call,
199
+ state=authoritative_state,
200
+ host=host,
201
+ ),
202
+ }
203
+
204
+
205
+ def describe_exposed_mcp_tools(
206
+ engine: Engine,
207
+ *,
208
+ compiler_input: str,
209
+ host: CalendarAdminMcpHost,
210
+ ) -> McpDecisionResult:
211
+ """Return the currently exposed MCP tools after applying compiler input."""
212
+
213
+ decision = engine.step(compiler_input)
214
+
215
+ if is_clarify(decision):
216
+ return {
217
+ "decision_kind": "clarify",
218
+ "prompt_to_user": decision.get("prompt_to_user"),
219
+ "exposed_tools": host.exposed_mcp_tools(engine.state),
220
+ }
221
+
222
+ authoritative_state = get_decision_state(decision)
223
+ if authoritative_state is None:
224
+ authoritative_state = engine.state
225
+
226
+ return {
227
+ "decision_kind": _decision_kind_name(decision),
228
+ "prompt_to_user": decision.get("prompt_to_user"),
229
+ "exposed_tools": host.exposed_mcp_tools(authoritative_state),
230
+ }
231
+
232
+
233
+ def run_demo() -> McpToolExecutionResult:
234
+ """Run a deterministic MCP demonstration with explicit authorization state."""
235
+
236
+ engine = create_engine()
237
+ engine.step("use calendar_admin")
238
+ host = CalendarAdminMcpHost()
239
+
240
+ return execute_mcp_tool_if_allowed(
241
+ {
242
+ "tool_name": "calendar_admin_create_event",
243
+ "arguments": {
244
+ "calendar_id": "ops-admin",
245
+ "event_title": "Quarterly access review",
246
+ },
247
+ },
248
+ state=engine.state,
249
+ host=host,
250
+ )