Skip to content

Commit 0a49154

Browse files
committed
docs: add AGENTS.md for AI coding assistance context
1 parent ba16276 commit 0a49154

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

AGENTS.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# AI Context & Coding Guidelines
2+
3+
This document provides context, architectural decisions, and coding standards for AI assistants (GitHub Copilot, Cursor, etc.) working on the `mcp-agileday` repository.
4+
5+
## 1. Project Overview
6+
This is a **Model Context Protocol (MCP) Server** for the **Agileday** platform (SaaS).
7+
- **Goal:** Bridge Agileday's employee and competence data with LLMs.
8+
- **Language:** Python 3.11+
9+
- **Transport:** Supports both `stdio` (for local Docker/Desktop usage) and `http-streamable` (SSE) via Starlette/Uvicorn.
10+
11+
## 2. Architectural Patterns (CRITICAL)
12+
13+
### The "Raw ASGI" Pattern
14+
We use **Starlette** for routing, but we **DO NOT** use standard Starlette request/response handlers for the MCP endpoints.
15+
* **Why:** The `mcp` Python SDK writes responses directly to the ASGI `send` channel. If Starlette also tries to send a `Response` object, the server crashes with a "Double Response" runtime error.
16+
* **Rule:** When touching `src/agileday_server.py` transport layer, ensure the `MCPHandler` class uses the raw ASGI signature: `async def __call__(self, scope, receive, send)`.
17+
* **Do Not:** Do not refactor the MCP routes to return standard `starlette.responses.Response` objects unless handling errors *outside* the SDK logic.
18+
19+
### Logic Separation
20+
To ensure testability, we separate **Tool Definitions** from **Business Logic**.
21+
* **Pattern:**
22+
1. Define the tool in `list_tools`.
23+
2. In `call_tool`, immediately delegate to a helper function (e.g., `find_experts_logic`, `profile_logic`).
24+
3. The helper function performs the API call and string formatting.
25+
* **Benefit:** This allows unit tests (`tests/test_agileday_server.py`) to test logic without needing to mock the entire MCP server protocol.
26+
27+
## 3. Tech Stack & Dependencies
28+
* **Core:** `mcp` (Model Context Protocol SDK)
29+
* **Web Server:** `starlette`, `uvicorn`
30+
* **HTTP Client:** `requests` (for synchronous calls inside logic), `httpx` (for testing ASGI)
31+
* **Testing:** `pytest`
32+
33+
## 4. Testing Guidelines
34+
35+
### Unit Tests (`tests/test_agileday_server.py`)
36+
* **Scope:** Tests business logic functions (e.g., `find_experts_logic`).
37+
* **Mocking:** strictly mock `requests.get` using `unittest.mock.patch`. Never make real HTTP calls.
38+
* **Data:** Create minimal mock JSON responses that match the Agileday API structure (see `openapi.yaml` for reference).
39+
40+
### Transport Tests (`tests/test_transport.py`)
41+
* **Scope:** Tests the HTTP/SSE endpoints (`/mcp`, `/health`).
42+
* **Mocking Strategy:** Because the SDK writes to the network socket, mocks must simulate ASGI side effects.
43+
* **Pattern:**
44+
```python
45+
# Example of required mock behavior for handle_post_message
46+
async def side_effect(scope, receive, send):
47+
await send({'type': 'http.response.start', 'status': 202, ...})
48+
await send({'type': 'http.response.body', 'body': b'Accepted'})
49+
```
50+
51+
## 5. API Knowledge (Agileday)
52+
* **Authentication:** Bearer Token via `AGILEDAY_API_TOKEN`.
53+
* **Base URL:** `https://{tenant}.agileday.io/api`.
54+
* **Key Schemas:**
55+
* **Skills:** Contain `proficiency` (float), `motivation` (float), and `experience` (string/duration).
56+
* **Employees:** Return lists of skills.
57+
* **Terminology:** Use "Motivation" (internal data key), but it can be referred to as "Willingness" in user-facing output if requested.
58+
59+
## 6. Directory Structure
60+
```text
61+
.
62+
├── src/
63+
│ └── agileday_server.py # SINGLE FILE implementation (keep it simple)
64+
├── tests/
65+
│ ├── test_agileday_server.py # Logic tests
66+
│ └── test_transport.py # Server/Protocol tests
67+
├── Dockerfile # Production build (defaults to http transport)
68+
├── requirements.txt
69+
└── README.md
70+
71+
```
72+
73+
## 7. Common Tasks
74+
75+
### Adding a New Tool
76+
77+
- Add the Tool definition in list_tools.
78+
79+
- Add the dispatch logic in call_tool.
80+
81+
- Create a def new_tool_logic(...) -> str function.
82+
83+
- Add a test case in tests/test_agileday_server.py verifying the logic output.
84+
85+
### Improving Search
86+
When the user asks for "experts", always try to expose:
87+
88+
- Proficiency (Level)
89+
90+
- Experience Duration (if available in API)
91+
92+
- Motivation/Willingness (via the fire icon or text)

0 commit comments

Comments
 (0)