Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions demos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,4 @@ Integrations <ovms_demos_integrations>
|[Integration with Open WebUI](integration_with_OpenWebUI/README.md)|Using Open WebUI with OVMS as inference provider. Shows text and image generation as well as usage with RAG and tools.|
|[Visual Studio Code assistant](./code_local_assistant/README.md)|Use Continue extension in Visual Studio Code with local OVMS serving.|
|[Cline coding agent integration](./cline_integration/README.md)|Use the Cline coding agent in Visual Studio Code with local OVMS serving, including MCP, image input and reasoning_effort usage.|
|[Integration with DeepAgents Code](integration_with_deepagents_code/README.md)|Using DeepAgents Code with OVMS as inference provider. Shows MCP server creation, subagent-based validation and tool use.|
4 changes: 2 additions & 2 deletions demos/continuous_batching/structured_output/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ There are no extra steps needed to use structured output. Whole behavior is trig
**Required:** Docker Engine installed

```bash
mkdir models
mkdir -p ${HOME}/models
export GPU_ARGS=$(if ls /dev/dri/render* >/dev/null 2>&1; then echo "--device /dev/dri --group-add $(stat -c '%g' /dev/dri/render* | head -n1)"; fi)
docker run ${GPU_ARGS} --user $(id -u):$(id -g) -d --rm -p 8000:8000 -v $(pwd)/models:/models:rw openvino/model_server:latest-gpu --source_model OpenVINO/Mistral-7B-Instruct-v0.3-int4-cw-ov --model_repository_path /models --rest_port 8000
docker run ${GPU_ARGS} --user $(id -u):$(id -g) -d --rm -p 8000:8000 -v ${HOME}/models:/models:rw openvino/model_server:latest-gpu --source_model OpenVINO/Mistral-7B-Instruct-v0.3-int4-cw-ov --model_repository_path /models --rest_port 8000
```
:::
:::{tab-item} On Baremetal Host Windows
Expand Down
10 changes: 10 additions & 0 deletions demos/integration_with_deepagents_code/.deepagents/.mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"mcpServers": {
"time-server": {
"command": "python",
"args": [
"${DEMO_DIR}/mcp_server/time_mcp_server.py"
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
name: mcp-tester
description: Verifies local Python MCP stdio servers by static checks and short runtime startup checks.
model: openai:OpenVINO/Qwen3.8-27B-int4-ov
---

You are a focused subagent for MCP server verification.
Be concise. Do not explain your reasoning.
Do not produce plans or long commentary.

Goal:
- Verify that a local Python MCP stdio server is runnable.
- Return a short pass/fail report with concrete evidence.

What this subagent is responsible for:
- Inspect the target server script.
- Verify required elements exist: FastMCP usage, at least one @mcp.tool, and stdio run call.
- Run a syntax/import check: `python -m py_compile <server_path>`.
- Run a short startup check: `timeout 2s python <server_path>`.
- Read `.deepagents/.mcp.json` and confirm there is a matching stdio entry.

What this subagent is not responsible for:
- Writing or changing MCP config files.
- Refactoring unrelated project files.
- Long prose explanations.

Rules:
- Resolve paths from the current working directory.
- Treat `python -m py_compile <server_path>` as authoritative for syntax: any unterminated string, malformed docstring quote, or other parse error is a hard FAIL.
- If `py_compile` fails, include the exact syntax error line and message in the Evidence section.
- If `timeout 2s python <server_path>` exits with 124, treat that as expected for a long-running stdio server if no traceback appears.
- If startup exits non-zero with traceback, report failure and include the key error line.
- Do not claim success without command output evidence.
- Never return placeholders or template tokens such as `%stdio*`, `%args%`, `<server_path>`, `<exit_code>`, or `PASS/FAIL` literals without resolved values.
- If any evidence line contains unresolved placeholders, set Verdict to FAIL and report `placeholder_output` as the reason.
- Keep output short.

Output format:
1. Verdict: PASS or FAIL.
2. Checks:
- script_structure: PASS/FAIL
- py_compile: PASS/FAIL
- startup_timeout_run: PASS/FAIL
- mcp_config_match: PASS/FAIL
3. Evidence: exactly 4 lines, one per check, each containing:
- the exact command run,
- exit code,
- one concrete output fragment (stdout/stderr snippet or "no output").
4. If FAIL: a brief description of what failed, naming the failing check(s) and the key error or missing condition.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
name: python-mcp-sdk-skill
description: "Guidance for implementing Python MCP SDK stdio servers with FastMCP, robust validation, and deterministic tool output."
license: MIT
compatibility: designed for deepagents-code
---

# Python MCP SDK Server Builder

Use this skill when the user asks to create or modify an MCP server in Python.

## Goal
Build a minimal, production-safe MCP stdio server using the Python MCP SDK package `mcp`.

## Implementation pattern

1. Create `mcp_server/<name>_mcp_server.py`.
2. Use `FastMCP`.
3. Register one or more `@mcp.tool()` functions.
4. Add explicit docstrings and strict input validation.
5. Start with `mcp.run(transport="stdio")`.

## Required template

```python
from mcp.server.fastmcp import FastMCP
from mcp.types import ToolAnnotations

mcp = FastMCP("your-server-name")

# Reusable annotations for tools that only read state and never mutate anything.
READ_ONLY = ToolAnnotations(
readOnlyHint=True,
destructiveHint=False,
idempotentHint=True,
openWorldHint=False,
)


@mcp.tool(annotations=READ_ONLY)
def your_tool_name(arg: str) -> str:
"""Describe exactly what this tool returns."""
value = arg.strip()
if not value:
raise ValueError("arg cannot be empty")
return value


if __name__ == "__main__":
mcp.run(transport="stdio")
```

## Tool annotations — MANDATORY

Every `@mcp.tool()` MUST declare MCP tool annotations. Annotations tell hosts (like dcode) whether a tool is safe to call without user approval. Tools with no annotations are treated as "possibly mutating" and are rejected outright in dcode headless mode (`dcode -n ...`) with:

> "This MCP action requires approval, but the current headless runtime has no approval UI."

dcode's `HeadlessMCPGuardMiddleware` gates any tool whose metadata does not satisfy BOTH:
- `readOnlyHint is True`
- `destructiveHint is not True`

Choose the annotation set that matches the tool's real behavior:

| Tool behavior | Annotations |
|---------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
| Pure read (clock, config lookup, HTTP GET) | `readOnlyHint=True, destructiveHint=False, idempotentHint=True, openWorldHint=False` |
| Read that consults an external service (web/API) | `readOnlyHint=True, destructiveHint=False, idempotentHint=True, openWorldHint=True` |
| Idempotent write (set a value; same input twice = same result) | `readOnlyHint=False, destructiveHint=False, idempotentHint=True, openWorldHint=<True/False>` |
| Destructive write (delete, drop, DROP TABLE, rm) | `readOnlyHint=False, destructiveHint=True, idempotentHint=False, openWorldHint=<True/False>` |

Never claim `readOnlyHint=True` for a tool that mutates state. Lying to skip the approval gate is a security issue.

For tools that are NOT read-only, users must run them from the interactive TUI (approval required); document that limitation in the tool's docstring.

## Time tool recipe

When the user needs exact current time, expose:
- `get_current_utc_iso8601()` returning UTC timestamp in ISO 8601 with trailing Z.
- Optional timezone helper for named zones using `zoneinfo`.

Both are pure reads → annotate with `READ_ONLY` (see template above).

## Quality checks

- Avoid third-party dependencies beyond `mcp`.
- Do not use network calls unless required.
- Keep tool outputs deterministic and machine-readable.
- **Every tool must have `ToolAnnotations` matching its real behavior** — see the table above. Verify by running the tool from `dcode -n` after implementation; if it fails with the "approval, but the current headless runtime has no approval UI" message, the annotations are missing or wrong.
Loading