Compare commits

..
1 Commits
Author SHA1 Message Date
thanhnv 202925e6ed feat(mcp): scaffold three project context tools
CI / test (pull_request) Canceled after 0s
2026-08-20 20:50:37 +07:00
4 changed files with 28 additions and 6 deletions
+6 -5
View File
@@ -21,12 +21,13 @@ cần đổi, mở một PR nhỏ riêng và để cả ba người rebase sau k
## Bắt đầu trong 5 phút
1. Tạo branch từ commit template chứa tài liệu này sau khi PR template merge.
2. Đọc input/output model trong module tool được giao; không thêm field riêng của Gitea/Jira/Redmine.
3. Implement provider read-only trong module `providers/<tool>.py`; credential chỉ lấy sau policy ALLOW.
4. Thêm test happy, invalid, not-found, timeout, DENIED với `resolver.calls == 0`, output sai schema,
1. Chạy `python --version` và xác nhận Python 3.11+ như baseline trong `requirements.txt`.
2. Tạo branch từ commit template chứa tài liệu này sau khi PR template merge.
3. Đọc input/output model trong module tool được giao; không thêm field riêng của Gitea/Jira/Redmine.
4. Implement provider read-only trong module `providers/<tool>.py`; credential chỉ lấy sau policy ALLOW.
5. Thêm test happy, invalid, not-found, timeout, DENIED với `resolver.calls == 0`, output sai schema,
truncation/cursor và source mở được có `revision`.
5. Chạy:
6. Chạy:
```bash
python -m pytest tests/test_project_context_mcp_template.py tests/test_project_context_<tool>.py -q
+14
View File
@@ -3,6 +3,7 @@
from __future__ import annotations
import os
import sys
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
@@ -12,6 +13,18 @@ from .providers.change import build_provider as build_change_provider
from .providers.issue import build_provider as build_issue_provider
from .providers.knowledge import build_provider as build_knowledge_provider
MINIMUM_PYTHON = (3, 11)
def require_supported_python(version_info: tuple[int, ...] | None = None) -> None:
"""Fail with an actionable message before the MCP server starts."""
current = version_info or tuple(sys.version_info[:3])
if current[:2] < MINIMUM_PYTHON:
raise RuntimeError(
"Project Context MCP requires Python 3.11 or newer; "
f"current runtime is {current[0]}.{current[1]}"
)
@dataclass(frozen=True)
class ProjectScopePolicy:
@@ -46,6 +59,7 @@ def _required_environment(name: str) -> str:
def default_runtime() -> ProjectContextRuntime:
"""Build immutable runtime state; missing identity configuration fails at boot."""
require_supported_python()
identity = IdentityContext(
actor_id=_required_environment("COWORK_MCP_ACTOR_ID"),
org_unit=_required_environment("COWORK_MCP_ORG_UNIT"),
+2 -1
View File
@@ -17,7 +17,7 @@ from .foundation import (
error_result,
)
from .registry import TOOLS_BY_NAME, tool_declarations
from .runtime import default_runtime
from .runtime import default_runtime, require_supported_python
def dispatch(
@@ -102,6 +102,7 @@ def build_server(runtime: Optional[ProjectContextRuntime] = None):
from mcp import types
from mcp.server.lowlevel import Server
require_supported_python()
app_runtime = runtime or default_runtime()
app = Server("project_context")
@@ -12,6 +12,7 @@ from cowork_local.mcp_servers.project_context.registry import (
TOOL_NAMES,
tool_declarations,
)
from cowork_local.mcp_servers.project_context.runtime import require_supported_python
from cowork_local.mcp_servers.project_context.server import dispatch
from mcp import types
@@ -95,6 +96,11 @@ def test_template_exposes_exactly_three_provider_neutral_tools() -> None:
assert all(types.Tool(**item).name in EXPECTED_TOOLS for item in declarations)
def test_runtime_fails_fast_below_python_311() -> None:
with pytest.raises(RuntimeError, match="requires Python 3.11"):
require_supported_python((3, 9, 0))
def test_denied_request_never_resolves_credentials_or_calls_provider(
identity: IdentityContext,
) -> None: