dispatch_agents 0.14.2__tar.gz → 0.14.3__tar.gz

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 (163) hide show
  1. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/PKG-INFO +1 -1
  2. dispatch_agents-0.14.3/RELEASE_NOTES.md +2 -0
  3. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/mcp.py +36 -2
  4. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/pyproject.toml +1 -1
  5. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_mcp.py +68 -2
  6. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/uv.lock +1 -1
  7. dispatch_agents-0.14.2/RELEASE_NOTES.md +0 -2
  8. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.claude-plugin/marketplace.json +0 -0
  9. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/scripts/change_scope.py +0 -0
  10. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/scripts/ci_git.py +0 -0
  11. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/scripts/version_policy.py +0 -0
  12. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/tests/test_change_scope.py +0 -0
  13. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/tests/test_ci_git.py +0 -0
  14. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/tests/test_version_policy.py +0 -0
  15. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/workflows/ci-reusable.yml +0 -0
  16. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/workflows/feature-branch.yml +0 -0
  17. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/workflows/release.yml +0 -0
  18. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.github/workflows/version-policy-reusable.yml +0 -0
  19. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/.gitignore +0 -0
  20. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/CONTRIBUTING.md +0 -0
  21. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/LICENSE +0 -0
  22. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/LICENSE-3rdparty.csv +0 -0
  23. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/NOTICE +0 -0
  24. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/README.md +0 -0
  25. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/__init__.py +0 -0
  26. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/py.typed +0 -0
  27. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/__init__.py +0 -0
  28. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/message_pb2.py +0 -0
  29. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/message_pb2.pyi +0 -0
  30. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/message_pb2_grpc.py +0 -0
  31. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/request_response_pb2.py +0 -0
  32. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/request_response_pb2.pyi +0 -0
  33. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/request_response_pb2_grpc.py +0 -0
  34. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/service_pb2.py +0 -0
  35. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/service_pb2.pyi +0 -0
  36. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/agentservice/v1/service_pb2_grpc.py +0 -0
  37. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/__init__.py +0 -0
  38. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_deprecated_public_api.py +0 -0
  39. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/__init__.py +0 -0
  40. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/agent_service.py +0 -0
  41. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/bootstrap.py +0 -0
  42. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/config_validation.py +0 -0
  43. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/dev.py +0 -0
  44. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/dispatch.py +0 -0
  45. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/grpc_server.py +0 -0
  46. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/instrument.py +0 -0
  47. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/llm_langchain.py +0 -0
  48. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/models.py +0 -0
  49. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/proxy/__init__.py +0 -0
  50. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/proxy/server.py +0 -0
  51. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/proxy/sse_utils.py +0 -0
  52. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/transport.py +0 -0
  53. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/_internal/version.py +0 -0
  54. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/config.py +0 -0
  55. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/context.py +0 -0
  56. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/contrib/__init__.py +0 -0
  57. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/contrib/claude/__init__.py +0 -0
  58. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/contrib/openai/__init__.py +0 -0
  59. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/events.py +0 -0
  60. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/handlers.py +0 -0
  61. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/integrations/__init__.py +0 -0
  62. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/integrations/github/README.md +0 -0
  63. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/integrations/github/__init__.py +0 -0
  64. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/integrations/github/client.py +0 -0
  65. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/integrations/github/events.py +0 -0
  66. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/invocation.py +0 -0
  67. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/llm.py +0 -0
  68. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/logging.py +0 -0
  69. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/memory.py +0 -0
  70. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/models.py +0 -0
  71. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/py.typed +0 -0
  72. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/dispatch_agents/storage.py +0 -0
  73. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/README.md +0 -0
  74. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/company-researcher/.gitignore +0 -0
  75. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/company-researcher/AGENTS.md +0 -0
  76. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/company-researcher/README.md +0 -0
  77. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/company-researcher/agent.py +0 -0
  78. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/company-researcher/dispatch.yaml +0 -0
  79. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/company-researcher/pyproject.toml +0 -0
  80. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/company-researcher/uv.lock +0 -0
  81. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/conversational-agent/README.md +0 -0
  82. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/conversational-agent/agent.py +0 -0
  83. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/conversational-agent/dispatch.yaml +0 -0
  84. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/conversational-agent/pyproject.toml +0 -0
  85. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/daily-digest/README.md +0 -0
  86. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/daily-digest/agent.py +0 -0
  87. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/daily-digest/dispatch.yaml +0 -0
  88. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/daily-digest/pyproject.toml +0 -0
  89. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/deep-research/README.md +0 -0
  90. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/deep-research/agent.py +0 -0
  91. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/deep-research/configuration.py +0 -0
  92. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/deep-research/deep_researcher.py +0 -0
  93. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/deep-research/dispatch.yaml +0 -0
  94. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/deep-research/prompts.py +0 -0
  95. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/deep-research/pyproject.toml +0 -0
  96. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/deep-research/state.py +0 -0
  97. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/deep-research/tools.py +0 -0
  98. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/hello_world/.gitignore +0 -0
  99. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/hello_world/AGENTS.md +0 -0
  100. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/hello_world/README.md +0 -0
  101. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/hello_world/agent.py +0 -0
  102. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/hello_world/dispatch.yaml +0 -0
  103. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/hello_world/pyproject.toml +0 -0
  104. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/hello_world/test_agent.py +0 -0
  105. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/hello_world/uv.lock +0 -0
  106. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/knowledge-base-query/.env.example +0 -0
  107. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/knowledge-base-query/.gitignore +0 -0
  108. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/knowledge-base-query/AGENTS.md +0 -0
  109. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/knowledge-base-query/agent.py +0 -0
  110. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/knowledge-base-query/dispatch.yaml +0 -0
  111. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/knowledge-base-query/pyproject.toml +0 -0
  112. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/multi-framework/README.md +0 -0
  113. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/multi-framework/agent.py +0 -0
  114. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/multi-framework/dispatch.yaml +0 -0
  115. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/multi-framework/pyproject.toml +0 -0
  116. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/pyproject.toml +0 -0
  117. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/uv.lock +0 -0
  118. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-assistant/.gitignore +0 -0
  119. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-assistant/AGENTS.md +0 -0
  120. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-assistant/agent.py +0 -0
  121. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-assistant/dispatch.yaml +0 -0
  122. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-assistant/pyproject.toml +0 -0
  123. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-assistant/uv.lock +0 -0
  124. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-service/.gitignore +0 -0
  125. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-service/AGENTS.md +0 -0
  126. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-service/agent.py +0 -0
  127. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-service/dispatch.yaml +0 -0
  128. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-service/pyproject.toml +0 -0
  129. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/examples/weather-service/uv.lock +0 -0
  130. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/internal/py.typed +0 -0
  131. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/plugins/README.md +0 -0
  132. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/__init__.py +0 -0
  133. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/conftest.py +0 -0
  134. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/e2e_claude_mcp_proxy.py +0 -0
  135. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/schemas/README.md +0 -0
  136. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/schemas/octokit-webhooks.json +0 -0
  137. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test.py +0 -0
  138. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_agent_service.py +0 -0
  139. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_agent_uid.py +0 -0
  140. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_config.py +0 -0
  141. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_contrib_claude.py +0 -0
  142. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_contrib_openai.py +0 -0
  143. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_dev_mode_isolation.py +0 -0
  144. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_extra_headers.py +0 -0
  145. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_fn_decorator.py +0 -0
  146. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_github_client.py +0 -0
  147. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_github_integration.py +0 -0
  148. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_github_schema_compliance.py +0 -0
  149. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_grpc_server.py +0 -0
  150. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_init.py +0 -0
  151. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_instrument.py +0 -0
  152. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_llm_langchain.py +0 -0
  153. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_llm_logging.py +0 -0
  154. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_logging.py +0 -0
  155. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_memory.py +0 -0
  156. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_proxy_e2e.py +0 -0
  157. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_proxy_server.py +0 -0
  158. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_public_api.py +0 -0
  159. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_resources.py +0 -0
  160. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_sse_utils.py +0 -0
  161. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_trace_context.py +0 -0
  162. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/test_typed_events.py +0 -0
  163. {dispatch_agents-0.14.2 → dispatch_agents-0.14.3}/tests/typing_checks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dispatch_agents
3
- Version: 0.14.2
3
+ Version: 0.14.3
4
4
  Summary: Dispatch Agents SDK
5
5
  License-File: LICENSE
6
6
  License-File: LICENSE-3rdparty.csv
@@ -0,0 +1,2 @@
1
+ ## Bug Fixes
2
+ - MCP servers managed by Dispatch are now correctly skipped during local development, preventing unintended interactions with remotely managed server configurations.
@@ -26,6 +26,7 @@ from dispatch_agents._internal.dispatch import (
26
26
  get_current_trace_id,
27
27
  get_invocation_id_for_trace,
28
28
  )
29
+ from dispatch_agents.logging import get_logger
29
30
 
30
31
  if TYPE_CHECKING:
31
32
  from dispatch_agents.models import (
@@ -41,6 +42,8 @@ if TYPE_CHECKING:
41
42
 
42
43
  __all__ = ["MCPClient", "get_mcp_client", "get_mcp_servers_config"]
43
44
 
45
+ _logger = get_logger(__name__)
46
+
44
47
  MCP_CONFIG_PATH = os.environ.get("MCP_CONFIG_PATH", ".mcp.json")
45
48
 
46
49
 
@@ -282,14 +285,29 @@ def _get_dispatch_mcp_servers() -> dict[str, Any]:
282
285
 
283
286
  Constructs URLs and auth headers from runtime environment variables
284
287
  (``DISPATCH_MCP_GATEWAY_URL``, ``DISPATCH_NAMESPACE``, ``DISPATCH_API_KEY``).
285
- No file I/O.
288
+ No file I/O. Returns ``{}`` in local dev, where the gateway is unavailable.
286
289
  """
290
+ from dispatch_agents._internal.transport import is_local_dev_mode
287
291
  from dispatch_agents.config import _load_runtime_config
288
292
 
289
293
  cfg = _load_runtime_config()
290
294
  if not cfg.mcp_servers:
291
295
  return {}
292
296
 
297
+ # The MCP gateway is a deployed/production concern; it is not available under
298
+ # `dispatch agent dev` (the local router does not proxy /api/v1/mcp/...). Skip
299
+ # dispatch-managed servers in local dev rather than crashing on the missing
300
+ # gateway URL. Authors who want to exercise MCP locally supply a .mcp.json.
301
+ if is_local_dev_mode():
302
+ names = ", ".join(s.server for s in cfg.mcp_servers)
303
+ _logger.warning(
304
+ "Skipping dispatch-managed MCP server(s) in local dev mode: %s. "
305
+ "The MCP gateway is not available under `dispatch agent dev`. "
306
+ "To test MCP locally, define the server(s) in a .mcp.json file.",
307
+ names,
308
+ )
309
+ return {}
310
+
293
311
  gateway = _require_env("DISPATCH_MCP_GATEWAY_URL")
294
312
  namespace = os.environ.get("DISPATCH_NAMESPACE") or cfg.namespace
295
313
  if not namespace:
@@ -346,13 +364,25 @@ def _get_merged_mcp_servers() -> dict[str, Any]:
346
364
 
347
365
  def _get_server_config(server_name: str) -> dict[str, Any]:
348
366
  """Get configuration for a specific MCP server."""
367
+ from dispatch_agents._internal.transport import is_local_dev_mode
368
+
349
369
  servers = _get_merged_mcp_servers()
350
370
  if server_name not in servers:
351
371
  available = list(servers.keys())
352
- raise ValueError(
372
+ message = (
353
373
  f"MCP server '{server_name}' not found in config. "
354
374
  f"Available servers: {available}"
355
375
  )
376
+ # Dispatch-managed servers are skipped under `dispatch agent dev` (the
377
+ # local router does not proxy the MCP gateway), so a server declared in
378
+ # dispatch.yaml will be absent here. Point the author at the local escape
379
+ # hatch rather than leaving them with a bare "not found".
380
+ if is_local_dev_mode():
381
+ message += (
382
+ " Dispatch-managed MCP servers are skipped under `dispatch agent "
383
+ "dev`; define the server in a .mcp.json file to use it locally."
384
+ )
385
+ raise ValueError(message)
356
386
  return servers[server_name]
357
387
 
358
388
 
@@ -365,6 +395,10 @@ def get_mcp_servers_config() -> dict[str, McpHttpServerConfig]:
365
395
  is merged additively; duplicate names with dispatch-managed servers are
366
396
  rejected.
367
397
 
398
+ In local dev (``dispatch agent dev``) the MCP gateway is unavailable, so
399
+ dispatch-managed servers are skipped and only ``.mcp.json`` servers are
400
+ returned.
401
+
368
402
  Returns:
369
403
  Mapping of server name to HTTP URL and headers.
370
404
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "dispatch_agents"
7
- version = "0.14.2"
7
+ version = "0.14.3"
8
8
  description = "Dispatch Agents SDK"
9
9
  requires-python = ">=3.11"
10
10
  dependencies = [
@@ -5,6 +5,7 @@ config builders.
5
5
  """
6
6
 
7
7
  import json
8
+ import logging
8
9
  from unittest.mock import AsyncMock, MagicMock, patch
9
10
 
10
11
  import pytest
@@ -272,6 +273,7 @@ class TestGetDispatchMcpServers:
272
273
 
273
274
  def test_missing_required_env_raises(self, monkeypatch):
274
275
  monkeypatch.delenv("DISPATCH_MCP_GATEWAY_URL", raising=False)
276
+ monkeypatch.delenv("DISPATCH_LOCAL_DEV", raising=False)
275
277
  monkeypatch.setenv("DISPATCH_NAMESPACE", "ns")
276
278
  monkeypatch.setenv("DISPATCH_API_KEY", "key")
277
279
 
@@ -285,6 +287,33 @@ class TestGetDispatchMcpServers:
285
287
  ):
286
288
  _get_dispatch_mcp_servers()
287
289
 
290
+ def test_local_dev_skips_dispatch_servers(self, monkeypatch, caplog):
291
+ # In local dev the MCP gateway is unavailable, so dispatch-managed
292
+ # servers are skipped (with a warning) instead of crashing.
293
+ monkeypatch.setenv("DISPATCH_LOCAL_DEV", "true")
294
+ monkeypatch.delenv("DISPATCH_MCP_GATEWAY_URL", raising=False)
295
+
296
+ config = DispatchConfig(
297
+ mcp_servers=[MCPServerConfig(server="my-server")],
298
+ )
299
+
300
+ # The SDK logger sets propagate=False, so caplog's root handler never
301
+ # sees the record. Attach caplog's handler to the SDK logger directly.
302
+ sdk_logger = logging.getLogger("dispatch_agents")
303
+ sdk_logger.addHandler(caplog.handler)
304
+ try:
305
+ with patch(
306
+ "dispatch_agents.config._load_runtime_config", return_value=config
307
+ ):
308
+ with caplog.at_level("WARNING", logger="dispatch_agents"):
309
+ result = _get_dispatch_mcp_servers()
310
+ finally:
311
+ sdk_logger.removeHandler(caplog.handler)
312
+
313
+ assert result == {}
314
+ assert "local dev mode" in caplog.text
315
+ assert "my-server" in caplog.text
316
+
288
317
 
289
318
  class TestGetMergedMcpServers:
290
319
  def test_merges_dispatch_and_user_servers(self, tmp_path, monkeypatch):
@@ -326,6 +355,28 @@ class TestGetMergedMcpServers:
326
355
 
327
356
  assert list(result) == ["dispatch-server"]
328
357
 
358
+ def test_local_dev_uses_only_user_servers(self, tmp_path, monkeypatch):
359
+ # In local dev, dispatch-managed servers are skipped, so the merged set
360
+ # comes entirely from the user's .mcp.json -- no gateway URL required.
361
+ monkeypatch.setenv("DISPATCH_LOCAL_DEV", "true")
362
+ monkeypatch.delenv("DISPATCH_MCP_GATEWAY_URL", raising=False)
363
+
364
+ config = DispatchConfig(
365
+ mcp_servers=[MCPServerConfig(server="dispatch-server")],
366
+ )
367
+
368
+ user_config = {"mcpServers": {"user-server": {"url": "http://user:3000"}}}
369
+ config_file = tmp_path / ".mcp.json"
370
+ config_file.write_text(json.dumps(user_config))
371
+
372
+ with (
373
+ patch("dispatch_agents.config._load_runtime_config", return_value=config),
374
+ patch("dispatch_agents.mcp.MCP_CONFIG_PATH", str(config_file)),
375
+ ):
376
+ result = _get_merged_mcp_servers()
377
+
378
+ assert list(result) == ["user-server"]
379
+
329
380
  def test_duplicate_user_server_raises(self, tmp_path, monkeypatch):
330
381
  monkeypatch.setenv("DISPATCH_MCP_GATEWAY_URL", "https://gw.example.com")
331
382
  monkeypatch.setenv("DISPATCH_NAMESPACE", "ns")
@@ -350,13 +401,28 @@ class TestGetMergedMcpServers:
350
401
 
351
402
 
352
403
  class TestGetServerConfig:
353
- def test_not_found_raises(self, tmp_path):
404
+ def test_not_found_raises(self, tmp_path, monkeypatch):
405
+ monkeypatch.delenv("DISPATCH_LOCAL_DEV", raising=False)
354
406
  config = {"mcpServers": {"other-server": {"url": "http://localhost:3000"}}}
355
407
  config_file = tmp_path / ".mcp.json"
356
408
  config_file.write_text(json.dumps(config))
357
409
 
358
410
  with patch("dispatch_agents.mcp.MCP_CONFIG_PATH", str(config_file)):
359
- with pytest.raises(ValueError, match="not found in config"):
411
+ with pytest.raises(ValueError, match="not found in config") as exc_info:
412
+ _get_server_config("missing-server")
413
+ # Outside local dev, no dev-mode hint is appended.
414
+ assert "dispatch agent dev" not in str(exc_info.value)
415
+
416
+ def test_not_found_in_local_dev_hints_at_mcp_json(self, tmp_path, monkeypatch):
417
+ # In local dev a dispatch-managed server is skipped, so it is absent here.
418
+ # The error should point the author at the .mcp.json escape hatch instead
419
+ # of leaving them with a bare "not found".
420
+ monkeypatch.setenv("DISPATCH_LOCAL_DEV", "true")
421
+ config_file = tmp_path / ".mcp.json"
422
+ config_file.write_text(json.dumps({"mcpServers": {}}))
423
+
424
+ with patch("dispatch_agents.mcp.MCP_CONFIG_PATH", str(config_file)):
425
+ with pytest.raises(ValueError, match="dispatch agent dev"):
360
426
  _get_server_config("missing-server")
361
427
 
362
428
  def test_returns_server_config(self, tmp_path):
@@ -567,7 +567,7 @@ wheels = [
567
567
 
568
568
  [[package]]
569
569
  name = "dispatch-agents"
570
- version = "0.14.2"
570
+ version = "0.14.3"
571
571
  source = { editable = "." }
572
572
  dependencies = [
573
573
  { name = "aiohttp" },
@@ -1,2 +0,0 @@
1
- ## Features
2
- - The logging configuration module is now publicly accessible as `dispatch_agents.logging`, allowing users to directly import and use logging utilities from the top-level package.