deepagents-cli 0.1.0__tar.gz → 0.1.2__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 (96) hide show
  1. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/.gitignore +2 -0
  2. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/CHANGELOG.md +12 -0
  3. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/PKG-INFO +9 -1
  4. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/README.md +8 -0
  5. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/_version.py +1 -1
  6. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/commands.py +21 -1
  7. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/templates.py +38 -7
  8. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/package-lock.json +3 -3
  9. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/pyproject.toml +1 -1
  10. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/deploy/test_bundler.py +85 -0
  11. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/deploy/test_commands.py +28 -0
  12. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/uv.lock +5 -5
  13. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/DEV.md +0 -0
  14. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/Makefile +0 -0
  15. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/THREAT_MODEL.md +0 -0
  16. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/__init__.py +0 -0
  17. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/__main__.py +0 -0
  18. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/config.py +0 -0
  19. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/__init__.py +0 -0
  20. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/bundler.py +0 -0
  21. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/config.py +0 -0
  22. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/context_hub.py +0 -0
  23. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/frontend_dist/assets/anonymous-B9UzAXQd.js +0 -0
  24. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/frontend_dist/assets/clerk-5xHgyQyG.js +0 -0
  25. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/frontend_dist/assets/highlighted-body-OFNGDK62-rX-7qT8o.js +0 -0
  26. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/frontend_dist/assets/index-DM3gptpu.js +0 -0
  27. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/frontend_dist/assets/index-Ddy7F6KI.css +0 -0
  28. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/frontend_dist/assets/supabase-S6NACDgm.js +0 -0
  29. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/frontend_dist/index.html +0 -0
  30. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/frontend_dist/logo-dark.svg +0 -0
  31. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/deploy/frontend_dist/logo-light.svg +0 -0
  32. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/main.py +0 -0
  33. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/model_config.py +0 -0
  34. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/deepagents_cli/py.typed +0 -0
  35. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/deploy-content-writer/.env.example +0 -0
  36. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/deploy-content-writer/skills/blog-post/SKILL.md +0 -0
  37. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/deploy-content-writer/skills/social-media/SKILL.md +0 -0
  38. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/deploy-content-writer/user/context.md +0 -0
  39. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/deploy-content-writer/user/preferences.md +0 -0
  40. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/skills/arxiv-search/SKILL.md +0 -0
  41. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/skills/arxiv-search/arxiv_search.py +0 -0
  42. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/skills/langgraph-docs/SKILL.md +0 -0
  43. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/skills/skill-creator/SKILL.md +0 -0
  44. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/skills/skill-creator/scripts/init_skill.py +0 -0
  45. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/skills/skill-creator/scripts/quick_validate.py +0 -0
  46. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/examples/skills/web-research/SKILL.md +0 -0
  47. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/.nvmrc +0 -0
  48. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/index.html +0 -0
  49. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/package.json +0 -0
  50. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/postcss.config.js +0 -0
  51. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/public/logo-dark.svg +0 -0
  52. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/public/logo-light.svg +0 -0
  53. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/App.tsx +0 -0
  54. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/ThemeProvider.tsx +0 -0
  55. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/auth/anonymous.tsx +0 -0
  56. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/auth/clerk.tsx +0 -0
  57. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/auth/loader.tsx +0 -0
  58. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/auth/supabase.tsx +0 -0
  59. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/auth/types.ts +0 -0
  60. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/AppHeader.tsx +0 -0
  61. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/FilePanels.tsx +0 -0
  62. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/MessageList.tsx +0 -0
  63. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/SubagentActivity.tsx +0 -0
  64. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/ThreadPicker.tsx +0 -0
  65. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/TodosPanel.tsx +0 -0
  66. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/ToolCallCard.tsx +0 -0
  67. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/toolcalls/FileToolCard.tsx +0 -0
  68. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/toolcalls/SearchCard.tsx +0 -0
  69. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/toolcalls/ThinkCard.tsx +0 -0
  70. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/toolcalls/TodosCard.tsx +0 -0
  71. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/components/toolcalls/index.ts +0 -0
  72. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/constants.ts +0 -0
  73. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/index.css +0 -0
  74. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/main.tsx +0 -0
  75. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/runtimeConfig.ts +0 -0
  76. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/types.ts +0 -0
  77. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/src/vite-env.d.ts +0 -0
  78. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/tsconfig.json +0 -0
  79. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/frontend/vite.config.ts +0 -0
  80. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/images/cli.png +0 -0
  81. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/scripts/check_imports.py +0 -0
  82. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/scripts/debug_server.sh +0 -0
  83. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/scripts/install.sh +0 -0
  84. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/README.md +0 -0
  85. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/integration_tests/__init__.py +0 -0
  86. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/integration_tests/conftest.py +0 -0
  87. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/integration_tests/test_context_hub.py +0 -0
  88. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/integration_tests/test_deploy_hub.py +0 -0
  89. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/__init__.py +0 -0
  90. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/conftest.py +0 -0
  91. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/deploy/__init__.py +0 -0
  92. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/deploy/test_config.py +0 -0
  93. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/deploy/test_context_hub.py +0 -0
  94. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/deploy/test_frontend_bundle.py +0 -0
  95. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/deploy/test_frontend_config.py +0 -0
  96. {deepagents_cli-0.1.0 → deepagents_cli-0.1.2}/tests/unit_tests/test_version.py +0 -0
@@ -138,6 +138,8 @@ celerybeat.pid
138
138
  # Environments
139
139
  .env
140
140
  .envrc
141
+ env.local
142
+ *.env.local
141
143
  .venv
142
144
  env/
143
145
  venv/
@@ -3,6 +3,18 @@
3
3
  From 0.1.0 onward, `deepagents-cli` only contains `deploy`, `dev`, and `init`.
4
4
  The coding agent (interactive TUI & headless CLI) moved to [`deepagents-code`](https://github.com/langchain-ai/deepagents/blob/main/libs/code/CHANGELOG.md).
5
5
 
6
+ ## [0.1.2](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.1.1...deepagents-cli==0.1.2) (2026-05-21)
7
+
8
+ ### Bug Fixes
9
+
10
+ * Expand `${VAR}` in `mcp.json` header values ([#3523](https://github.com/langchain-ai/deepagents/issues/3523)) ([6cfc5f9](https://github.com/langchain-ai/deepagents/commit/6cfc5f9004271c23c486a0b05e8f9f0002e75e2b))
11
+
12
+ ## [0.1.1](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.1.0...deepagents-cli==0.1.1) (2026-05-18)
13
+
14
+ ### Features
15
+
16
+ * Add `--host` option to `deepagents dev` command ([#3444](https://github.com/langchain-ai/deepagents/issues/3444)) ([0bb1e74](https://github.com/langchain-ai/deepagents/commit/0bb1e74bba8097b38f204e3db6e6ebad7e0f5317))
17
+
6
18
  ## [0.1.0](https://github.com/langchain-ai/deepagents/compare/deepagents-cli==0.0.59...deepagents-cli==0.1.0) (2026-05-16)
7
19
 
8
20
  ### ⚠ BREAKING CHANGES
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-cli
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Deployment tooling for Deep Agents - bundle, run, and ship agents to LangGraph Platform.
5
5
  Project-URL: Homepage, https://docs.langchain.com/oss/python/deepagents/overview
6
6
  Project-URL: Documentation, https://reference.langchain.com/python/deepagents/
@@ -55,6 +55,14 @@ Description-Content-Type: text/markdown
55
55
  [![PyPI - Downloads](https://img.shields.io/pepy/dt/deepagents-cli)](https://pypistats.org/packages/deepagents-cli)
56
56
  [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/langchain_oss.svg?style=social&label=Follow%20%40LangChain)](https://x.com/langchain_oss)
57
57
 
58
+ > [!IMPORTANT]
59
+ > **The interactive coding agent moved.** As of `deepagents-cli==0.1.0`, this package contains only the deployment subcommands (`init`, `dev`, `deploy`). The interactive REPL — previously launched via `deepagents` — now ships as [`deepagents-code`](https://docs.langchain.com/oss/python/deepagents/code/overview) (`dcode`).
60
+ >
61
+ > ```bash
62
+ > curl -LsSf https://langch.in/dcode | bash
63
+ > dcode
64
+ > ```
65
+
58
66
  ## Install
59
67
 
60
68
  ```bash
@@ -5,6 +5,14 @@
5
5
  [![PyPI - Downloads](https://img.shields.io/pepy/dt/deepagents-cli)](https://pypistats.org/packages/deepagents-cli)
6
6
  [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/langchain_oss.svg?style=social&label=Follow%20%40LangChain)](https://x.com/langchain_oss)
7
7
 
8
+ > [!IMPORTANT]
9
+ > **The interactive coding agent moved.** As of `deepagents-cli==0.1.0`, this package contains only the deployment subcommands (`init`, `dev`, `deploy`). The interactive REPL — previously launched via `deepagents` — now ships as [`deepagents-code`](https://docs.langchain.com/oss/python/deepagents/code/overview) (`dcode`).
10
+ >
11
+ > ```bash
12
+ > curl -LsSf https://langch.in/dcode | bash
13
+ > dcode
14
+ > ```
15
+
8
16
  ## Install
9
17
 
10
18
  ```bash
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Keep the `x-release-please-version` annotation — release-please uses it to
4
4
  # bump `__version__` in sync with `pyproject.toml` on every release PR.
5
- __version__ = "0.1.0" # x-release-please-version
5
+ __version__ = "0.1.2" # x-release-please-version
6
6
 
7
7
  DOCS_URL = "https://docs.langchain.com/oss/python/deepagents/cli"
8
8
  """URL for `deepagents-cli` documentation."""
@@ -84,6 +84,15 @@ def setup_deploy_parsers(
84
84
  default=True,
85
85
  help="Pass --allow-blocking to langgraph dev (default: enabled)",
86
86
  )
87
+ dev_parser.add_argument(
88
+ "--host",
89
+ type=str,
90
+ default="127.0.0.1",
91
+ help=(
92
+ "Network interface to bind the dev server "
93
+ "(default: 127.0.0.1; use 0.0.0.0 for all interfaces)"
94
+ ),
95
+ )
87
96
 
88
97
  # deepagents deploy
89
98
  deploy_parser = subparsers.add_parser(
@@ -138,6 +147,7 @@ def execute_dev_command(args: argparse.Namespace) -> None:
138
147
  _dev(
139
148
  config_path=args.config,
140
149
  port=args.port,
150
+ host=args.host,
141
151
  allow_blocking=args.allow_blocking,
142
152
  )
143
153
 
@@ -343,6 +353,7 @@ def _dev(
343
353
  *,
344
354
  config_path: str | None,
345
355
  port: int,
356
+ host: str = "127.0.0.1",
346
357
  allow_blocking: bool,
347
358
  ) -> None:
348
359
  """Bundle the project and run a local `langgraph dev` server.
@@ -356,6 +367,7 @@ def _dev(
356
367
  Args:
357
368
  config_path: Path to `deepagents.toml`, or `None` for default.
358
369
  port: Local port for the dev server.
370
+ host: Network interface to bind (default: 127.0.0.1).
359
371
  allow_blocking: Pass `--allow-blocking` to `langgraph dev` so
360
372
  sync HTTP calls inside the graph (e.g. the LangSmith sandbox
361
373
  client) don't trigger blockbuster errors.
@@ -413,13 +425,21 @@ def _dev(
413
425
  "langgraph",
414
426
  "dev",
415
427
  "--no-browser",
428
+ "--host",
429
+ host,
416
430
  "--port",
417
431
  str(port),
418
432
  ]
419
433
  if allow_blocking:
420
434
  cmd.append("--allow-blocking")
421
435
 
422
- print(f"\nStarting langgraph dev on http://localhost:{port}")
436
+ if host == "0.0.0.0":
437
+ print(
438
+ f"\nStarting langgraph dev on http://localhost:{port} "
439
+ "(bound to 0.0.0.0)"
440
+ )
441
+ else:
442
+ print(f"\nStarting langgraph dev on http://{host}:{port}")
423
443
  print(f"Build directory: {build_dir}")
424
444
  print(f"Running: {' '.join(cmd)}\n")
425
445
 
@@ -409,10 +409,28 @@ AUTH_BLOCKS: dict[str, tuple[str, str | None]] = {
409
409
 
410
410
  MCP_TOOLS_TEMPLATE = '''\
411
411
  async def _load_mcp_tools():
412
- """Load MCP tools from bundled config (http/sse only)."""
412
+ """Load MCP tools from bundled config (http/sse only).
413
+
414
+ The `url` and `headers` values support `${VAR}` references which are
415
+ expanded against `os.environ` when the deployed graph loads. This
416
+ mirrors the substitution behavior documented for `deepagents-code`'s
417
+ `.mcp.json` (https://docs.langchain.com/oss/python/deepagents/code/mcp-tools).
418
+ Unset variables are left as the literal `${VAR}` so the resulting auth
419
+ failure surfaces a recognizable token rather than an empty header.
420
+ """
413
421
  import json
422
+ import os
423
+ import re
414
424
  from pathlib import Path
415
425
 
426
+ def _expand(value):
427
+ """Expand `${VAR}` references in strings; pass other types through."""
428
+ if isinstance(value, str):
429
+ return os.path.expandvars(value)
430
+ return value
431
+
432
+ unresolved_re = re.compile(r"\\$\\{[^}]+\\}")
433
+
416
434
  mcp_path = Path(__file__).parent / "_mcp.json"
417
435
  if not mcp_path.exists():
418
436
  return []
@@ -428,9 +446,23 @@ async def _load_mcp_tools():
428
446
  for name, cfg in servers.items():
429
447
  transport = cfg.get("type", cfg.get("transport", "stdio"))
430
448
  if transport in ("http", "sse"):
431
- conn = {"transport": transport, "url": cfg["url"]}
449
+ conn = {"transport": transport, "url": _expand(cfg["url"])}
432
450
  if "headers" in cfg:
433
- conn["headers"] = cfg["headers"]
451
+ conn["headers"] = {
452
+ k: _expand(v) for k, v in cfg["headers"].items()
453
+ }
454
+ unresolved = sorted({
455
+ match
456
+ for value in (conn["url"], *conn.get("headers", {}).values())
457
+ if isinstance(value, str)
458
+ for match in unresolved_re.findall(value)
459
+ })
460
+ if unresolved:
461
+ logger.warning(
462
+ "MCP server %r has unresolved environment reference(s): %s",
463
+ name,
464
+ ", ".join(unresolved),
465
+ )
434
466
  connections[name] = conn
435
467
 
436
468
  if not connections:
@@ -441,11 +473,10 @@ async def _load_mcp_tools():
441
473
 
442
474
  client = MultiServerMCPClient(connections)
443
475
  return await client.get_tools()
444
- except Exception as exc: # noqa: BLE001
445
- logger.warning(
446
- "Failed to load MCP tools from %d server(s): %s",
476
+ except Exception:
477
+ logger.exception(
478
+ "Failed to load MCP tools from %d server(s)",
447
479
  len(connections),
448
- exc,
449
480
  )
450
481
  return []
451
482
  '''
@@ -6091,9 +6091,9 @@
6091
6091
  }
6092
6092
  },
6093
6093
  "node_modules/ws": {
6094
- "version": "8.20.0",
6095
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
6096
- "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
6094
+ "version": "8.20.1",
6095
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
6096
+ "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
6097
6097
  "license": "MIT",
6098
6098
  "engines": {
6099
6099
  "node": ">=10.0.0"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "deepagents-cli"
7
- version = "0.1.0"
7
+ version = "0.1.2"
8
8
  description = "Deployment tooling for Deep Agents - bundle, run, and ship agents to LangGraph Platform."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -2,7 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import asyncio
5
6
  import json
7
+ import logging
8
+ import sys
9
+ import types
6
10
  from typing import TYPE_CHECKING
7
11
 
8
12
  import pytest
@@ -207,6 +211,87 @@ class TestRenderDeployGraph:
207
211
  assert "_load_mcp_tools" not in result
208
212
  assert "pass # no MCP servers configured" in result
209
213
 
214
+ def test_mcp_loader_expands_env_vars(
215
+ self,
216
+ tmp_path: Path,
217
+ monkeypatch: pytest.MonkeyPatch,
218
+ caplog: pytest.LogCaptureFixture,
219
+ ) -> None:
220
+ """Emitted loader expands `${VAR}` in url + headers before MCP connect.
221
+
222
+ Mirrors the `${VAR}` substitution behavior of `deepagents-code`'s
223
+ `.mcp.json`. Without this, headers like
224
+ `Authorization: Bearer ${TOKEN}` reach MCP servers as the literal
225
+ string and auth fails silently.
226
+
227
+ Also verifies the documented contracts: unset references are left as
228
+ literal `${VAR}` so a recognizable token surfaces, non-string header
229
+ values pass through unchanged, and unresolved tokens emit a warning.
230
+ """
231
+ from deepagents_cli.deploy.templates import MCP_TOOLS_TEMPLATE
232
+
233
+ captured: dict[str, dict] = {}
234
+
235
+ class _FakeClient:
236
+ def __init__(self, connections: dict) -> None:
237
+ captured["connections"] = connections
238
+
239
+ async def get_tools(self) -> list:
240
+ return []
241
+
242
+ fake_root = types.ModuleType("langchain_mcp_adapters")
243
+ fake_client = types.ModuleType("langchain_mcp_adapters.client")
244
+ fake_client.MultiServerMCPClient = _FakeClient # type: ignore[attr-defined]
245
+ monkeypatch.setitem(sys.modules, "langchain_mcp_adapters", fake_root)
246
+ monkeypatch.setitem(sys.modules, "langchain_mcp_adapters.client", fake_client)
247
+
248
+ (tmp_path / "_mcp.json").write_text(
249
+ json.dumps(
250
+ {
251
+ "mcpServers": {
252
+ "primary": {
253
+ "type": "http",
254
+ "url": "https://api.example.com/${ENDPOINT}",
255
+ "headers": {
256
+ "Authorization": "Bearer ${TOKEN}",
257
+ "X-Unset": "value-${MISSING_VAR}",
258
+ "X-Numeric": 42,
259
+ },
260
+ },
261
+ },
262
+ },
263
+ ),
264
+ encoding="utf-8",
265
+ )
266
+
267
+ monkeypatch.setenv("ENDPOINT", "v1/chat")
268
+ monkeypatch.setenv("TOKEN", "secret-abc")
269
+ monkeypatch.delenv("MISSING_VAR", raising=False)
270
+
271
+ loader_logger = logging.getLogger("test_mcp_loader")
272
+ namespace: dict = {
273
+ "__file__": str(tmp_path / "graph.py"),
274
+ "logger": loader_logger,
275
+ }
276
+ exec(
277
+ compile(MCP_TOOLS_TEMPLATE, "<MCP_TOOLS_TEMPLATE>", "exec"),
278
+ namespace,
279
+ )
280
+
281
+ with caplog.at_level(logging.WARNING, logger="test_mcp_loader"):
282
+ asyncio.run(namespace["_load_mcp_tools"]())
283
+
284
+ conn = captured["connections"]["primary"]
285
+ assert conn["url"] == "https://api.example.com/v1/chat"
286
+ assert conn["headers"]["Authorization"] == "Bearer secret-abc"
287
+ assert conn["headers"]["X-Unset"] == "value-${MISSING_VAR}"
288
+ assert conn["headers"]["X-Numeric"] == 42
289
+ assert any(
290
+ "unresolved environment reference" in rec.getMessage()
291
+ and "${MISSING_VAR}" in rec.getMessage()
292
+ for rec in caplog.records
293
+ )
294
+
210
295
  def test_no_system_prompt_in_output(self) -> None:
211
296
  """AGENTS.md should not be baked into the deploy graph as a system prompt."""
212
297
  config = _minimal_config()
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import argparse
5
6
  from types import SimpleNamespace
6
7
  from typing import TYPE_CHECKING, cast
7
8
 
@@ -197,3 +198,30 @@ class TestAutoWireIssuesBoard:
197
198
  _auto_wire_issues_board_if_hub(cast("DeployConfig", cfg))
198
199
 
199
200
  assert observed["context_hub_repo_handle"] == "custom-agent"
201
+
202
+
203
+ class TestDevParserHost:
204
+ """Test argparse wiring for the `deepagents dev --host` flag."""
205
+
206
+ def _build_parser(self) -> argparse.ArgumentParser:
207
+ from deepagents_cli.deploy.commands import setup_deploy_parsers
208
+
209
+ class _NoopAction(argparse.Action):
210
+ def __call__(self, *_args: object, **_kwargs: object) -> None:
211
+ return
212
+
213
+ parser = argparse.ArgumentParser()
214
+ subparsers = parser.add_subparsers(dest="command")
215
+ setup_deploy_parsers(
216
+ subparsers,
217
+ make_help_action=lambda _printer: _NoopAction,
218
+ )
219
+ return parser
220
+
221
+ def test_host_defaults_to_loopback(self) -> None:
222
+ args = self._build_parser().parse_args(["dev"])
223
+ assert args.host == "127.0.0.1"
224
+
225
+ def test_host_accepts_all_interfaces(self) -> None:
226
+ args = self._build_parser().parse_args(["dev", "--host", "0.0.0.0"])
227
+ assert args.host == "0.0.0.0"
@@ -792,7 +792,7 @@ wheels = [
792
792
 
793
793
  [[package]]
794
794
  name = "deepagents"
795
- version = "0.6.1"
795
+ version = "0.6.3"
796
796
  source = { editable = "../deepagents" }
797
797
  dependencies = [
798
798
  { name = "langchain" },
@@ -836,7 +836,7 @@ test = [
836
836
 
837
837
  [[package]]
838
838
  name = "deepagents-cli"
839
- version = "0.1.0"
839
+ version = "0.1.2"
840
840
  source = { editable = "." }
841
841
  dependencies = [
842
842
  { name = "deepagents" },
@@ -1399,11 +1399,11 @@ wheels = [
1399
1399
 
1400
1400
  [[package]]
1401
1401
  name = "idna"
1402
- version = "3.11"
1402
+ version = "3.15"
1403
1403
  source = { registry = "https://pypi.org/simple" }
1404
- sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" }
1404
+ sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" }
1405
1405
  wheels = [
1406
- { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
1406
+ { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" },
1407
1407
  ]
1408
1408
 
1409
1409
  [[package]]
File without changes
File without changes