summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ollama_web/llm.py18
-rw-r--r--src/ollama_web/mcp.py20
2 files changed, 8 insertions, 30 deletions
diff --git a/src/ollama_web/llm.py b/src/ollama_web/llm.py
index 11e93d2..693cfa2 100644
--- a/src/ollama_web/llm.py
+++ b/src/ollama_web/llm.py
@@ -10,8 +10,9 @@ from typing import Any, cast
import ollama
from ollama import Message
+
from .config import settings
-from .mcp import is_dangerous_mcp_tool, redact_secrets
+from .mcp import redact_secrets
from .tools.registry import ToolRegistry, default_registry
# Maximum successive tool-call rounds before we force a final answer.
@@ -38,14 +39,7 @@ def _safe_tool_result(result: str) -> str:
return str(redacted)
-def _execute_tool_with_policy(
- reg: ToolRegistry,
- name: str,
- args: Any,
-) -> str:
- if is_dangerous_mcp_tool(name):
- return json.dumps({"error": "MCP tool requires explicit approval"}, ensure_ascii=False)
- return reg.execute(name, args if isinstance(args, dict) else json.dumps(args))
+
def get_client(host: str | None = None) -> ollama.Client:
@@ -265,8 +259,9 @@ def chat_with_tools(
for call in calls:
name = call.get("name", "")
args = call.get("arguments", {})
+
yield {"type": "tool_start", "name": name, "arguments": _safe_tool_arguments(args)}
- result = _execute_tool_with_policy(reg, name, args)
+ result = reg.execute(name, args if isinstance(args, dict) else json.dumps(args))
result = _safe_tool_result(_trim_tool_result(result, settings.max_tool_result_chars))
yield {"type": "tool_end", "name": name, "result": result}
tool_results.append((name, result))
@@ -443,10 +438,11 @@ def stream_chat_with_tools(
for call in tool_calls:
name = call.get("name", "")
args = call.get("arguments", {})
+
yield {"type": "tool_start", "name": name, "arguments": _safe_tool_arguments(args)}
t1 = time.time()
try:
- result = _execute_tool_with_policy(reg, name, args)
+ result = reg.execute(name, args if isinstance(args, dict) else json.dumps(args))
except Exception as exc: # noqa: BLE001
logger.warning("tool %s execution failed in %.2fs: %s", name, time.time() - t1, exc)
result = f"Tool execution failed: {exc}"
diff --git a/src/ollama_web/mcp.py b/src/ollama_web/mcp.py
index 3437a62..e52860b 100644
--- a/src/ollama_web/mcp.py
+++ b/src/ollama_web/mcp.py
@@ -26,18 +26,8 @@ DEFAULT_TIMEOUT = 30.0
_MCP_TOOL_PREFIX = "mcp__"
_SAFE_NAME_RE = re.compile(r"^[A-Za-z0-9_-]{1,64}$")
_MAX_TOOL_DESCRIPTION_CHARS = 1000
+
_MAX_SCHEMA_DESCRIPTION_CHARS = 500
-_DANGEROUS_TOOL_WORDS = (
- "delete",
- "remove",
- "write",
- "exec",
- "shell",
- "command",
- "run",
- "token",
- "secret",
-)
_SECRET_KEY_RE = re.compile(r"(?i)(authorization|api[_-]?key|token|secret|cookie|session)")
_SECRET_VALUE_PATTERNS = (
re.compile(r"(?i)Bearer\s+[A-Za-z0-9._~+/=-]+"),
@@ -259,14 +249,6 @@ def wrap_untrusted_tool_output(text: str) -> str:
return f"{_UNTRUSTED_PREFIX}\n<tool-output>\n{body}\n</tool-output>"
-def is_dangerous_mcp_tool(name: str) -> bool:
- """Return whether an MCP tool name should require explicit approval."""
- parsed = _parse_tool_name(name)
- if parsed is None:
- return False
- lowered = parsed[1].lower()
- return any(word in lowered for word in _DANGEROUS_TOOL_WORDS)
-
def _to_ollama_tool(server_name: str, tool: Any) -> dict[str, Any]:
"""Convert an MCP ``Tool`` object into an ollama-compatible tool dict.