{"slug": "dgx-spark-msi-edgexpert-and-cubi-nuc-agents-the-loop", "title": "DGX Spark (MSI EdgeXpert) and Cubi Nuc: Agents, \"The Loop\"", "summary": "MSI's EdgeXpert, an Nvidia DGX Spark with 128GB of RAM, can remotely control an MSI Cubi NUC AI+ running Windows 11 to launch programs and run tools, according to a Level1Techs demonstration. The setup runs local models including Nemotron Omni for voice and video and Nemotron Nano for reasoning and agentic tasks, paired with the Turnstone harness and a Windows MCP server that exposes tools to AI agents. The DGX Spark can also run Nemotron Omni Super at NVFP4, which uses about two-thirds of available memory at maximum context, as well as Qwen A35B in NVFP4 format for coding and judging.", "body_md": "Here’s the video for context:\n\n## \n\nYou may have also heard executives saying that “computers were now using computers” and this is a little bit of insight into what that means.\n\n###### \n\nThis is the MSI EdgeXpert – an nvidia DGX Spark\n\nIt has 128gb ram and can run many AI models. We [reviewed it separately here](https://www.youtube.com/watch?v=sx6ANedcIfI), and [even got Steam running on it](https://forum.level1techs.com/t/nvidia-spark-gb10-msi-edgexpert-running-steam-games-cyberpunk-2077-doom-eternal-and-more-quickie-how-to/240557) natively (preview of RTX spark anyone?) .\n\nAnd here’s our Windows 11 MSI Cubi NUC AI+\n\n[We also reviewed it separately, here.](https://www.youtube.com/watch?v=taqoWdMxKhI)\n\nThe DGX Spark can basically marionette Windows 11, launch programs and run tools on it.\n\n# \n\nThe goal is to run local intelligence on the DGX spark and setup a Model Context Protocol (MCP) server on the MSI Cubi Nuc AI+ mini pc, running windows.\n\nThere are a lot of models that run well on the DGX spark; for the video we used Nemotron Omni for the voice and video capabilities, and Nemotron Nano for reasoning and agentic tasks. [Nvidia has great writeups](https://build.nvidia.com/spark/nemotron) on how to get this sort of thing going on your spark.\n\nThe other part of this is Turnstone:\n\nTurnstone is a *harness* which means you can hook up an AI model and give it an ability to do things – tool calling.\n\nTypically getting AI to do things effectively (quickly, lowest number of tokens, consistently) typically depends on tool calling and skills. Skills are often markdown files and, optionally, utility or helper scripts). The skill explains to the AI how to call a tool or tools (or helper scripts), how to interpret the output and most importantly what success criteria looks like. This gives the model context for what you have asked it to accomplish, and what success looks like.\n\nYou may have heard the term Agentic before.. what it means in this context is that your harness software (Turnstone in our case) could spawn several “chat” sessions that have different instructions but are all working toward the same goal.\n\nTODO: PIC\n\nThat’s why this is called an orchestrator – it’s orchestrating several sessions with the AI model. Think of each of these as an AI chat session except that you have tool calling (for generic tools), Skills (which can provide their own tools/scripts), and, the big thing in our video here, access to MCP interfaces.\n\nSo, in summary:\n\n## \n\n- MSI EdgeXpert / DGX Spark\n- MSI Cubi NUC AI+ running Windows 11\n- Turnstone\n- Windows-MCP\n- Nemotron Nano / Omni, or another OpenAI-compatible local model endpoint\n\n# \n\nMCP provides a standardized interface layer that also exposes tools and describes functionality. Think of it like an API but with built-in documentation. We can run an MCP server on the Cubi Nuc AI+ and then AI Agents running inside our Turnstone harness have the tools that the MCP server reports.\n\nFor this demo we’ll be using this Windows MCP server:\n\n# \n\n## \n\nFirst, setup the DGX Spark with both the Nemotron Omni and Nemotron Nano models.\n\nIt is possible to run Nemotron Omni Super on here; at NVFP4 it uses about 2/3 of the available memory at maximum context, and leaves enough room to also run Nemotron Omni in the background for voice and video.\n\nAnd, of course Models like Qwen A35B, also available in NVFP4 format, can run. Qwen makes an excellent coding and judge model, and is reasonably fast.\n\n### \n\n- Install the Nemotron model(s) you want to use\n- Confirm the OpenAI-compatible endpoint works.\n- Test with a simple completion.\n\n#### \n\n```\nsudo apt install -y ca-certificates curl gnupg python3-pip python3-venv jq\n```\n\nI am assuming your Spark already has docker and the nvidia container toolkit installed. It should. It should also have `python3`\n\n```\npython3 -m pip install -U \"huggingface_hub[hf_xet]\" --break-system-packages\n```\n\nLog into hugging face, or don’t (and just have slower downloads)\n\n```\nhf auth login\nhf auth whoami\n\nexport HF_TOKEN=\"$(cat ~/.cache/huggingface/token)\"\nmkdir -p ~/models\n```\n\nThe main setup in the video is 2 main models running on Spark, then some optional other configurations:\n\nNemotron Omni for Speech, Image and Video reasoning\n\nNemotron Nano: A 35B A3B model which is small and competent\n\n**Optional:**\n\nNemotron Super: It’s 120b so it’ll be slower and put more memory pressure on. Tough to get other optional models running at the same time due to memory pressure, especially if you want maximum context.\n\nGemma4 E4B: its just 4 billion effective parameters, but it makes a pretty good “judge” model for Turnstone. Gemma3 12b can also make a good judge, but in BF16 it’ll consume 24gb vram not 12. SFP8 is an option… but!\n\n**Qwen is also amazing!** And if you’re doing agentic coding tasks, then the 27B NVFP4 version of Qwen is worth a look on this hardware. That is a dense model – all 27 billion parameters are active at once – so it’ll be slower. There is also the 35B A3B version of Qwen 3.6, which runs much faster, but the NVFP4 version was just released and has some bugs in the response template or with tool-calling.\n\n**However, see note about nvfp4 versions of Qwen! **\n\n#### \n\nHF card: nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4. NVIDIA’s card says to use vLLM, download the custom nano_v3_reasoning_parser.py, enable auto tool choice, use qwen3_coder, and use FP8 KV cache; it recommends temperature=0.6/top_p=0.95 for tool calling.\n\nHere’s an example hf download command:\n\n```\nhf download nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4 \\\n  --local-dir ~/models/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4\n```\n\nHere’s the full script I used for this one, which will auto download the model if you don’t have it using `hf`\n\n```\nexport MODEL_ID=\"nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4\"\nexport WEIGHTS=\"$HOME/models/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4\"\n\nhf download \"$MODEL_ID\" \\\n  --local-dir \"$WEIGHTS\" \\\n  --max-workers 8\n\ntest -f \"$WEIGHTS/config.json\" && echo \"weights OK\"\ntest -f \"$WEIGHTS/nano_v3_reasoning_parser.py\" || \\\n  curl -L -o \"$WEIGHTS/nano_v3_reasoning_parser.py\" \\\n  https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4/resolve/main/nano_v3_reasoning_parser.py\n\ndocker run --rm -it \\\n  --name vllm-nemotron3-nano \\\n  --gpus all \\\n  --ipc=host \\\n  --shm-size=16g \\\n  -p 8000:8000 \\\n  -e HF_TOKEN=\"$HF_TOKEN\" \\\n  -e VLLM_USE_FLASHINFER_MOE_FP4=1 \\\n  -e VLLM_FLASHINFER_MOE_BACKEND=throughput \\\n  -v \"$WEIGHTS:/model:ro\" \\\n  -v \"$WEIGHTS/nano_v3_reasoning_parser.py:/app/nano_v3_reasoning_parser.py:ro\" \\\n  vllm/vllm-openai:v0.20.0 \\\n  /model \\\n    --served-model-name nvidia/nemotron-3-nano \\\n    --host 0.0.0.0 \\\n    --port 8000 \\\n    --trust-remote-code \\\n    --tensor-parallel-size 1 \\\n    --max-model-len 262144 \\\n    --max-num-seqs 8 \\\n    --gpu-memory-utilization 0.85 \\\n    --kv-cache-dtype fp8 \\\n    --enable-auto-tool-choice \\\n    --tool-call-parser qwen3_coder \\\n    --reasoning-parser-plugin /app/nano_v3_reasoning_parser.py \\\n    --reasoning-parser nano_v3\n```\n\nThe first time you create and run this script you will get output like:\n\nas it downloads the model to `~/.model`\n\n#### \n\nBuild page: `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning`. HF: `nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-NVFP4`. NVIDIA describes it as multimodal: video, audio, image, and text, with OCR/speech/video/document workflows. The Spark-specific Build recipe uses vLLM 0.20.0, mounts local weights, installs `vllm[audio]` inside the container, enables multimodal limits, sets video FPS/frames, and enables tool calling with the `qwen3_coder` style tool calling template.\n\nScript I used for the video to download, then run Omni:\n\n```\nhf download nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-NVFP4 \\\n  --local-dir ```/models/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-NVFP4\nbash\n#!/usr/bin/env bash\nset -euo pipefail\n\nMODEL_BASE=\"${HOME}/models\"\nMODEL_NAME=\"Nemotron-3-Nano-Omni-30B-A3B-Reasoning-NVFP4\"\nMODEL_DIR=\"${MODEL_BASE}/${MODEL_NAME}\"\nCONTAINER_MODEL_DIR=\"/models/${MODEL_NAME}\"\n\nCONTAINER_NAME=\"vllm-nemotron3-omni\"\nPORT=\"8001\"\n\necho \"Starting Nemotron 3 Nano Omni on http://localhost:${PORT}/v1\"\necho \"Host model path: ${MODEL_DIR}\"\necho \"Container model path: ${CONTAINER_MODEL_DIR}\"\n\nif [[ ! -f \"${MODEL_DIR}/config.json\" ]]; then\n  echo \"ERROR: ${MODEL_DIR}/config.json not found.\"\n  echo\n  echo \"Download the model first:\"\n  echo \"hf download nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-NVFP4 \\\\\"\n  echo \"  --local-dir ${MODEL_DIR}\"\n  exit 1\nfi\n\ndocker rm -f \"${CONTAINER_NAME}\" 2>/dev/null || true\n\ndocker run -d \\\n  --name \"${CONTAINER_NAME}\" \\\n  --restart unless-stopped \\\n  --gpus all \\\n  --ipc=host \\\n  --shm-size=16g \\\n  -p \"${PORT}:8000\" \\\n  -e HF_TOKEN=\"${HF_TOKEN:-}\" \\\n  -e FLASHINFER_DISABLE_VERSION_CHECK=1 \\\n  -v \"${MODEL_DIR}:${CONTAINER_MODEL_DIR}:ro\" \\\n  vllm/vllm-openai:v0.20.0 \\\n  \"${CONTAINER_MODEL_DIR}\" \\\n    --served-model-name nvidia/nemotron-3-nano-omni \\\n    --host 0.0.0.0 \\\n    --port 8000 \\\n    --max-num-seqs 1 \\\n    --max-model-len 32768 \\\n    --trust-remote-code \\\n    --gpu-memory-utilization 0.25 \\\n    --limit-mm-per-prompt '{\"video\": 1, \"image\": 1, \"audio\": 1}' \\\n    --media-io-kwargs '{\"video\": {\"fps\": 2, \"num_frames\": 128}}' \\\n    --allowed-local-media-path / \\\n    --max-num-batched-tokens 16384 \\\n    --reasoning-parser nemotron_v3 \\\n    --enable-auto-tool-choice \\\n    --tool-call-parser qwen3_coder\n\necho \"Nemotron 3 Nano Omni is starting on http://localhost:${PORT}/v1\"\necho \"Logs: docker logs -f ${CONTAINER_NAME}\"\necho \"Models: curl -sS http://localhost:${PORT}/v1/models | jq\"\n```\n\n#### \n\nOptional; use this instead of Nemotron 3 Nano or Qwen3.6 27B\n\n``` bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nMODEL_BASE=\"${HOME}/models\"\nMODEL_NAME=\"NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4\"\nMODEL_DIR=\"${MODEL_BASE}/${MODEL_NAME}\"\nCONTAINER_MODEL_DIR=\"/models/${MODEL_NAME}\"\n\nCONTAINER_NAME=\"vllm-nemotron3-super\"\nPORT=\"8002\"\nVLLM_IMAGE=\"vllm/vllm-openai:v0.20.0\"\n\necho \"Starting Nemotron 3 Super 120B A12B NVFP4 on http://localhost:${PORT}/v1\"\necho \"Host model path: ${MODEL_DIR}\"\necho \"Container model path: ${CONTAINER_MODEL_DIR}\"\necho \"vLLM image: ${VLLM_IMAGE}\"\n\nif [[ ! -f \"${MODEL_DIR}/config.json\" ]]; then\n  echo \"ERROR: ${MODEL_DIR}/config.json not found.\"\n  echo\n  echo \"Download the model first:\"\n  echo \"hf download nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4 \\\\\"\n  echo \"  --local-dir ${MODEL_DIR}\"\n  exit 1\nfi\n\nif [[ ! -f \"${MODEL_DIR}/super_v3_reasoning_parser.py\" ]]; then\n  echo \"ERROR: ${MODEL_DIR}/super_v3_reasoning_parser.py not found.\"\n  echo\n  echo \"Re-run:\"\n  echo \"hf download nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4 \\\\\"\n  echo \"  --local-dir ${MODEL_DIR}\"\n  exit 1\nfi\n\ndocker rm -f \"${CONTAINER_NAME}\" 2>/dev/null || true\n\ndocker run -d \\\n  --name \"${CONTAINER_NAME}\" \\\n  --restart unless-stopped \\\n  --gpus all \\\n  --ipc=host \\\n  --shm-size=16g \\\n  --ulimit memlock=-1 \\\n  --ulimit stack=67108864 \\\n  -p \"${PORT}:8000\" \\\n  -e HF_TOKEN=\"${HF_TOKEN:-}\" \\\n  -e VLLM_NVFP4_GEMM_BACKEND=marlin \\\n  -e VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 \\\n  -e VLLM_FLASHINFER_ALLREDUCE_BACKEND=trtllm \\\n  -e VLLM_USE_FLASHINFER_MOE_FP4=0 \\\n  -v \"${MODEL_DIR}:${CONTAINER_MODEL_DIR}:ro\" \\\n  -v \"${MODEL_DIR}/super_v3_reasoning_parser.py:/app/super_v3_reasoning_parser.py:ro\" \\\n  \"${VLLM_IMAGE}\" \\\n    --model \"${CONTAINER_MODEL_DIR}\" \\\n    --served-model-name nvidia/nemotron-3-super \\\n    --host 0.0.0.0 \\\n    --port 8000 \\\n    --async-scheduling \\\n    --dtype auto \\\n    --kv-cache-dtype fp8 \\\n    --tensor-parallel-size 1 \\\n    --pipeline-parallel-size 1 \\\n    --data-parallel-size 1 \\\n    --trust-remote-code \\\n    --gpu-memory-utilization 0.90 \\\n    --enable-chunked-prefill \\\n    --max-num-seqs 4 \\\n    --max-model-len 1000000 \\\n    --moe-backend marlin \\\n    --mamba_ssm_cache_dtype float16 \\\n    --quantization fp4 \\\n    --speculative_config '{\"method\":\"mtp\",\"num_speculative_tokens\":3,\"moe_backend\":\"triton\"}' \\\n    --reasoning-parser-plugin /app/super_v3_reasoning_parser.py \\\n    --reasoning-parser super_v3 \\\n    --enable-auto-tool-choice \\\n    --tool-call-parser qwen3_coder\n\necho \"Nemotron 3 Super is starting on http://localhost:${PORT}/v1\"\necho \"Logs: docker logs -f ${CONTAINER_NAME}\"\necho \"Models: curl -sS http://localhost:${PORT}/v1/models | jq\"\n```\n\n#### \n\nThis is optiona; you should look at the **ALTERNATE WAY** section below. The judge in turnstone typically needs 64k+ context; this can put some strain on on the configuration.\n\n``` bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nMODEL_BASE=\"${HOME}/models\"\n\n# Replace this with the exact downloaded Gemma 4 judge model directory.\n# Examples might be something like:\n#   gemma-4-e4b-it\n#   gemma-4-e4b-it-sfp8\n#   gemma-4-26b-a4b-it\nMODEL_NAME=\"gemma-4-e4b-it\"\n\nMODEL_DIR=\"${MODEL_BASE}/${MODEL_NAME}\"\nCONTAINER_MODEL_DIR=\"/models/${MODEL_NAME}\"\n\nCONTAINER_NAME=\"vllm-gemma4-judge\"\nPORT=\"8003\"\n\necho \"Starting Gemma 4 judge model on http://localhost:${PORT}/v1\"\necho \"Host model path: ${MODEL_DIR}\"\necho \"Container model path: ${CONTAINER_MODEL_DIR}\"\n\nif [[ ! -f \"${MODEL_DIR}/config.json\" ]]; then\n  echo \"ERROR: ${MODEL_DIR}/config.json not found.\"\n  echo\n  echo \"Download the model first, for example:\"\n  echo \"hf download google/${MODEL_NAME} \\\\\"\n  echo \"  --local-dir ${MODEL_DIR}\"\n  exit 1\nfi\n\ndocker rm -f \"${CONTAINER_NAME}\" 2>/dev/null || true\n\ndocker run -d \\\n  --name \"${CONTAINER_NAME}\" \\\n  --restart unless-stopped \\\n  --gpus all \\\n  --ipc=host \\\n  --shm-size=8g \\\n  -p \"${PORT}:8000\" \\\n  -e HF_TOKEN=\"${HF_TOKEN:-}\" \\\n  -e FLASHINFER_DISABLE_VERSION_CHECK=1 \\\n  -v \"${MODEL_DIR}:${CONTAINER_MODEL_DIR}:ro\" \\\n  vllm/vllm-openai:v0.20.0 \\\n  \"${CONTAINER_MODEL_DIR}\" \\\n    --served-model-name google/gemma-4-judge \\\n    --host 0.0.0.0 \\\n    --port 8000 \\\n    --trust-remote-code \\\n    --tensor-parallel-size 1 \\\n    --dtype auto \\\n    --max-model-len 65535 \\\n    --max-num-seqs 2 \\\n    --gpu-memory-utilization 0.25 \\\n    --kv-cache-dtype fp8 \\\n    --enable-prefix-caching\n\necho \"Gemma 4 judge model is starting on http://localhost:${PORT}/v1\"\necho \"Logs: docker logs -f ${CONTAINER_NAME}\"\necho \"Models: curl -sS http://localhost:${PORT}/v1/models | jq\"\n```\n\n**Note:** Do not try to run all four models at once! If you’re running nvfp4 Super then you might not even want to run Omni!\n\n#### \n\nThey are also *amazing* models!\n\nThey need vllm nightly, and sometimes the chat template or mtp can be sketchy. That’s one thing I’ve been stuck on the last few weeks.. it can be the difference between 15 and 45 t/s.. plus everyone always overlooks the utility and coherence of the model output. We want that to be as high as possible.\n\nHere are some starter scripts for Qwen3.6 A35B:\n\n``` bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nMODEL_BASE=\"${HOME}/models\"\nMODEL_NAME=\"Qwen3.6-35B-A3B-NVFP4\"\nMODEL_DIR=\"${MODEL_BASE}/${MODEL_NAME}\"\nCONTAINER_MODEL_DIR=\"/models/${MODEL_NAME}\"\n\nCONTAINER_NAME=\"vllm-qwen36-35b-a3b\"\nPORT=\"8005\"\n\n# Official model card says vllm/vllm-openai:nightly.\n# Community reports v0.23.0-class images also work on DGX Spark.\nVLLM_IMAGE=\"${VLLM_IMAGE:-vllm/vllm-openai:nightly}\"\n\necho \"Starting Qwen3.6 35B A3B NVFP4 on http://localhost:${PORT}/v1\"\necho \"Host model path: ${MODEL_DIR}\"\necho \"Container model path: ${CONTAINER_MODEL_DIR}\"\necho \"vLLM image: ${VLLM_IMAGE}\"\n\nif [[ ! -f \"${MODEL_DIR}/config.json\" ]]; then\n  echo \"ERROR: ${MODEL_DIR}/config.json not found.\"\n  echo\n  echo \"Download the model first:\"\n  echo \"hf download nvidia/Qwen3.6-35B-A3B-NVFP4 \\\\\"\n  echo \"  --local-dir ${MODEL_DIR}\"\n  exit 1\nfi\n\ndocker rm -f \"${CONTAINER_NAME}\" 2>/dev/null || true\n\ndocker run -d \\\n  --name \"${CONTAINER_NAME}\" \\\n  --restart unless-stopped \\\n  --gpus all \\\n  --ipc=host \\\n  --shm-size=16g \\\n  --ulimit memlock=-1 \\\n  --ulimit stack=67108864 \\\n  -p \"${PORT}:8000\" \\\n  -e HF_TOKEN=\"${HF_TOKEN:-}\" \\\n  -e FLASHINFER_DISABLE_VERSION_CHECK=1 \\\n  -e VLLM_USE_FLASHINFER_MOE_FP4=0 \\\n  -e VLLM_FP8_MOE_BACKEND=flashinfer_cutlass \\\n  -e CUTE_DSL_ARCH=sm_121a \\\n  -e VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 \\\n  -v \"${MODEL_DIR}:${CONTAINER_MODEL_DIR}:ro\" \\\n  --entrypoint /bin/bash \\\n  \"${VLLM_IMAGE}\" \\\n  -lc \"exec vllm serve '${CONTAINER_MODEL_DIR}' \\\n    --served-model-name nvidia/qwen3.6-35b-a3b \\\n    --host 0.0.0.0 \\\n    --port 8000 \\\n    --tensor-parallel-size 1 \\\n    --trust-remote-code \\\n    --dtype auto \\\n    --kv-cache-dtype fp8 \\\n    --quantization modelopt \\\n    --attention-backend flashinfer \\\n    --moe-backend marlin \\\n    --gpu-memory-utilization 0.40 \\\n    --max-model-len 262144 \\\n    --max-num-seqs 4 \\\n    --max-num-batched-tokens 8192 \\\n    --enable-chunked-prefill \\\n    --async-scheduling \\\n    --enable-prefix-caching \\\n    --load-format fastsafetensors \\\n    --reasoning-parser qwen3 \\\n    --enable-auto-tool-choice \\\n    --tool-call-parser qwen3_xml \\\n    --speculative-config '{\\\"method\\\":\\\"mtp\\\",\\\"num_speculative_tokens\\\":3,\\\"moe_backend\\\":\\\"triton\\\"}'\"\n\necho \"Qwen3.6 35B A3B NVFP4 is starting on http://localhost:${PORT}/v1\"\necho \"Logs: docker logs -f ${CONTAINER_NAME}\"\necho \"Models: curl -sS http://localhost:${PORT}/v1/models | jq\"\n```\n\nUnderstand that generally I’ve found the 27B model to be the most coherent on this model, but also much slower. The further wrinkle is that the Unsloth 4 bit quant version of Qwen3.6 27B doesn’t seem to have the same chat template/tool calling bugs the NVFP4 version does.\n\n*This is something that will have to be updated in this guide over time as things evolve.*  Watch the video for more context/nuance.\n\nNote: For all these example scripts the context length and the gpu memory utilization is a bit fungible. You’re meant to think about that and play with that number a bit as you come up with something that would work for your use case.\n\n## \n\n```\ncurl -fsSL https://raw.githubusercontent.com/turnstonelabs/turnstone/main/run.sh | bash\n```\n\n…Check out the video for setting up Turnstone; it’s pretty slick.\n\nMake sure that at least one AI container is running because the  installer can connect to the AI container to get it to help you set everything up.\n\n**ALTERNATE WAY:** So if you have any experience here, you may be questioning the wisdom of running multiple vLLM containers on DGX spark. That might not be a *best fit* for what we want to accomplish. So check this out:\n\n[turnstone/turnstone/deploy/vllm-litellm at main · turnstonelabs/turnstone · GitHub](https://github.com/turnstonelabs/turnstone/tree/main/turnstone/deploy/vllm-litellm)\n\nReasoning, Perception and re-ranking models at once (this also applies to Strix Halo!)\n\nThis is using Qwen 3.6 27B in nvfp4; vLLM nightly has had some performance regressions at the time of this write-up, but it is possible to achieve about 20t/s. This also works natively with `HF_HOME` so you don’t need to manually download models to the ~/models dir (and, infact, you shouldn’t).\n\nThis way gives you more model (more context) functionality, and uses 117 of the 121gb memory on my system.\n\n## \n\nInstall python 3, and ux, etc\n\n## \n\n```\npython -m uv tool run windows-mcp serve --transport streamable-http --host 192.168.0.115 --port 8000 --auth-key ItsForTheLulzOrWhateverYouChose\n```\n\n#### \n\nHF card: `nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4`. This is one of the best models that can be run on Spark, but it is slower: 120B total, 12B active, NVFP4, tool calling, and MTP. The Spark-specific HF command uses `vllm/vllm-openai:v0.20.0`, `VLLM_NVFP4_GEMM_BACKEND=marlin`, `--quantization fp4`, `--speculative_config '{\"method\":\"mtp\",\"num_speculative_tokens\":3,...}'`\n\nscript:\n\n``` bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nMODEL_BASE=\"${HOME}/models\"\nMODEL_NAME=\"NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4\"\nMODEL_DIR=\"${MODEL_BASE}/${MODEL_NAME}\"\nCONTAINER_MODEL_DIR=\"/models/${MODEL_NAME}\"\n\nCONTAINER_NAME=\"vllm-nemotron3-super\"\nPORT=\"8002\"\nVLLM_IMAGE=\"vllm/vllm-openai:v0.20.0\"\n\necho \"Starting Nemotron 3 Super 120B A12B NVFP4 on http://localhost:${PORT}/v1\"\necho \"Host model path: ${MODEL_DIR}\"\necho \"Container model path: ${CONTAINER_MODEL_DIR}\"\necho \"vLLM image: ${VLLM_IMAGE}\"\n\nif [[ ! -f \"${MODEL_DIR}/config.json\" ]]; then\n  echo \"ERROR: ${MODEL_DIR}/config.json not found.\"\n  echo\n  echo \"Download the model first:\"\n  echo \"hf download nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-NVFP4 \\\\\"\n  echo \"  --local-dir ${MODEL_DIR}\"\n  exit 1\nfi\n\nif [[ ! -f \"${MODEL_DIR}/super_v3_reasoning_parser.py\" ]]; then\n  echo \"ERROR: ${MODEL_DIR}/super_v3_reasoning_parser.py not found.\"\n  echo\n  echo \"Re-run the HF download or fetch the parser from the model repo.\"\n  exit 1\nfi\n\ndocker rm -f \"${CONTAINER_NAME}\" 2>/dev/null || true\n\ndocker run -d \\\n  --name \"${CONTAINER_NAME}\" \\\n  --restart unless-stopped \\\n  --gpus all \\\n  --ipc=host \\\n  --shm-size=16g \\\n  --ulimit memlock=-1 \\\n  --ulimit stack=67108864 \\\n  -p \"${PORT}:8000\" \\\n  -e HF_TOKEN=\"${HF_TOKEN:-}\" \\\n  -e VLLM_NVFP4_GEMM_BACKEND=marlin \\\n  -e VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 \\\n  -e VLLM_FLASHINFER_ALLREDUCE_BACKEND=trtllm \\\n  -e VLLM_USE_FLASHINFER_MOE_FP4=0 \\\n  -e FLASHINFER_DISABLE_VERSION_CHECK=1 \\\n  -v \"${MODEL_DIR}:${CONTAINER_MODEL_DIR}:ro\" \\\n  -v \"${MODEL_DIR}/super_v3_reasoning_parser.py:/app/super_v3_reasoning_parser.py:ro\" \\\n  \"${VLLM_IMAGE}\" \\\n  \"${CONTAINER_MODEL_DIR}\" \\\n    --served-model-name nvidia/nemotron-3-super \\\n    --host 0.0.0.0 \\\n    --port 8000 \\\n    --async-scheduling \\\n    --dtype auto \\\n    --kv-cache-dtype fp8 \\\n    --tensor-parallel-size 1 \\\n    --pipeline-parallel-size 1 \\\n    --data-parallel-size 1 \\\n    --trust-remote-code \\\n    --gpu-memory-utilization 0.90 \\\n    --enable-chunked-prefill \\\n    --max-num-seqs 4 \\\n    --max-model-len 1000000 \\\n    --moe-backend marlin \\\n    --mamba_ssm_cache_dtype float16 \\\n    --quantization fp4 \\\n    --speculative_config '{\"method\":\"mtp\",\"num_speculative_tokens\":3,\"moe_backend\":\"triton\"}' \\\n    --reasoning-parser-plugin /app/super_v3_reasoning_parser.py \\\n    --reasoning-parser super_v3 \\\n    --enable-auto-tool-choice \\\n    --tool-call-parser qwen3_coder\n\necho \"Nemotron 3 Super is starting on http://localhost:${PORT}/v1\"\necho \"Logs: docker logs -f ${CONTAINER_NAME}\"\necho \"Models: curl -sS http://localhost:${PORT}/v1/models | jq\"\n```\n\n## \n\nand configure the mcp sever:\n\nNote that you need `Authorization: Bearer`  and then the token you specified on the CLI.\n\n*I also recommend you setup TLS as in the TLS example for this windows MCP server so that the communications layer is encrypted on your lan, but one problem at a time. *\n\nYou should see:\n\nyou may also want to click `Sync to nodes`\n\n## \n\nI was surprised by how unnecessarily cumbersome this was.\n\nThe whole secret, and the place where the Hermes installer breaks down for the uninitiated, is that they make it too easy to break if you don’t want to cloud-host your AI, or go through their router.\n\nThe desktop gui did not work for setting up a [http://192.168.x.y](http://192.168.x.y). type local address.\n\n1. Install Hermes (their website/walkthrough is sufficient for this).\n2. You can create an account, but when it asks for an ai provider you can go with defaults or skip over it.\n3. run a terminal and do hermes setup. Pick FULL setup.\n4. For the model provider, pick custom, around option 32.\n5. Enter the url and port of the DGX Spark/EdgeXpert: [http://192.168.0.166:8000/v1](http://192.168.0.166:8000/v1)\n6. it should auto detect the model and context. You want to use the smartest model with hermes, ideally.\n\nIf you have two sparks you can try the new deepseek v4 flash nvfp4, or even run “only” the nemotron 120b parameter model as well.\n\nAs shown in the video, it’s pretty impressive to go from this:\n\nto this\n\nto this\n\nin just a few minutes.\n\n## \n\nThis is very basic, but if you want something a little more advanced.. i.e. a skill that can use `bash` for example, check this out:\n\nThis blog post is **a year old** at the time I’m writing this, but it still pretty relevant for wrapping your head around the possibilities. And everything has moved 10 years in the last year, so it’s even better:\n\n[Create Your Own Bash Computer Use Agent with NVIDIA Nemotron in One Hour | NVIDIA Technical Blog](https://developer.nvidia.com/blog/create-your-own-bash-computer-use-agent-with-nvidia-nemotron-in-one-hour/?ncid=pa-srch-goog-800119&_bt=806892606897&_bk=building%20an%20ai%20agent&_bm=p&_bn=g&_bg=199556538841&gad_source=1&gad_campaignid=23676241337&gbraid=0AAAAAD4XAoG2jbMngIF7gfmWQmGOR30Jf&gclid=EAIaIQobChMIkJyqi9bFlQMVnIzCCB0m2illEAAYASAAEgJbhfD_BwE)\n\n[Anthropic also has a skills repo on GitHub if you want to read and understand.](https://github.com/anthropics/skills)", "url": "https://wpnews.pro/news/dgx-spark-msi-edgexpert-and-cubi-nuc-agents-the-loop", "canonical_source": "https://forum.level1techs.com/t/dgx-spark-msi-edgexpert-and-cubi-nuc-agents-the-loop/252183#post_17", "published_at": "2026-09-22 17:10:08+00:00", "updated_at": "2026-09-22 17:25:31.025219+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "large-language-models", "ai-infrastructure"], "entities": ["MSI EdgeXpert", "Nvidia DGX Spark", "MSI Cubi NUC AI+", "Turnstone", "Windows-MCP", "Nemotron Omni", "Nemotron Nano", "Qwen A35B"], "alternates": {"html": "https://wpnews.pro/news/dgx-spark-msi-edgexpert-and-cubi-nuc-agents-the-loop", "markdown": "https://wpnews.pro/news/dgx-spark-msi-edgexpert-and-cubi-nuc-agents-the-loop.md", "text": "https://wpnews.pro/news/dgx-spark-msi-edgexpert-and-cubi-nuc-agents-the-loop.txt", "jsonld": "https://wpnews.pro/news/dgx-spark-msi-edgexpert-and-cubi-nuc-agents-the-loop.jsonld"}}