@foundation0/api 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/mcp/AGENTS.md ADDED
@@ -0,0 +1,130 @@
1
+ # MCP Endpoint Design (LLM-Friendly)
2
+
3
+ This folder contains the Foundation0 MCP server (`api/mcp/server.ts`) and CLI (`api/mcp/cli.ts`).
4
+
5
+ These notes exist because the most common “LLM friction” issues are predictable:
6
+ - tool name/prefix confusion (duplicate names, “tool not found”),
7
+ - payload-shape confusion (positional `args` vs object options, or proxy tools that require JSON strings),
8
+ - oversized responses (truncation → extra tool calls),
9
+ - weak errors (not actionable → retries and wasted calls).
10
+
11
+ Use this doc when adding or modifying MCP endpoints so models can succeed in **one call**.
12
+
13
+ ## 1) Avoid Tool Prefix Double-Wrapping
14
+
15
+ If your agent uses `pi-mcp-adapter` (or any MCP proxy that already prefixes tools), do **not** also run the server with `--tools-prefix`.
16
+
17
+ Bad (creates confusing duplicates like `f0_f0_net_curl` and `f0_net_curl`):
18
+ - Agent tool prefixing: `toolPrefix: "server"` (adds `f0_...`)
19
+ - Server tool prefixing: `--tools-prefix f0` (adds `f0....`)
20
+
21
+ Good (single predictable name):
22
+ - Agent: `toolPrefix: "server"`
23
+ - Server: no `--tools-prefix`
24
+
25
+ ## 2) Prefer Direct Tools for Hot Paths (Fewer Calls, Fewer Errors)
26
+
27
+ Proxy-based MCP gateways often require passing `args` as a **JSON string** (not an object), which LLMs frequently get wrong.
28
+
29
+ If a tool is used often (HTTP, search, file ops), expose it as a **direct tool** in the agent config:
30
+
31
+ ```json
32
+ {
33
+ "mcp": {
34
+ "mcpServers": {
35
+ "f0": {
36
+ "directTools": ["net_curl", "batch"]
37
+ }
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ Note: Direct tool names must be OpenAI-tool-name-safe (no dots). Use the underscore aliases (e.g., `net_curl`) when exposing direct tools.
44
+
45
+ Benefits:
46
+ - The model calls `f0_net_curl` directly (no gateway wrapper).
47
+ - The model passes a normal JSON object (no “args must be a JSON string” confusion).
48
+ - Tool discoverability improves (tool appears in the system prompt).
49
+
50
+ Guideline: keep direct tools to a focused set (5–20). Use proxy for large catalogs.
51
+
52
+ ## 3) Always Support a “Structured Mode” (Don’t Force Curl-CLI Literacy)
53
+
54
+ LLMs naturally try:
55
+ ```json
56
+ { "url": "https://…", "method": "GET", "headers": { "accept": "application/json" } }
57
+ ```
58
+
59
+ If your tool only accepts positional CLI-like args (e.g. `{ "args": ["-L", "…"] }`), the model will often:
60
+ - guess the wrong shape,
61
+ - call `describe`,
62
+ - retry,
63
+ - and burn multiple tool calls.
64
+
65
+ Best practice:
66
+ - support **both** shapes:
67
+ - Curl-style: `{ "args": ["-L", "https://…"] }`
68
+ - Structured: `{ "url": "https://…", "method": "GET", ... }`
69
+
70
+ For `net.curl` (alias `net_curl`), structured mode should accept the common fields:
71
+ - `url`/`urls`, `method`, `headers`, `body`/`data`/`json`, `followRedirects`, `includeHeaders`,
72
+ - `fail`, `silent`, `verbose`, `writeOut`,
73
+ - `timeoutMs`, `maxTimeSeconds`, `maxRedirects`,
74
+ - `output`/`remoteName`, `user`.
75
+
76
+ Also: keep field names intuitive (`url`, `method`, `headers`, `body`) even if internally you translate to an `args[]` array.
77
+
78
+ ## 4) Write a Tight Schema + Examples (Make the First Call Succeed)
79
+
80
+ Tool schemas are often the only thing an LLM sees.
81
+
82
+ Do:
83
+ - Provide a schema that shows **both** modes (positional `args[]` + structured keys).
84
+ - Add short descriptions that include **an example payload**.
85
+ - Prefer `additionalProperties: true` to allow forwards-compatible additions.
86
+
87
+ Avoid:
88
+ - schemas that only describe `args` but not recommended “structured mode”.
89
+ - schema-required fields that don’t exist for the other mode.
90
+
91
+ ## 5) Make Errors Actionable (Self-Correct in One Retry)
92
+
93
+ When rejecting input:
94
+ - Use clear “what you passed / what I expected” wording.
95
+ - Include a copy/paste example.
96
+ - Provide likely tool-name suggestions when tool lookup fails.
97
+
98
+ If you control the gateway layer:
99
+ - Treat argument-shape failures as `isError: true` so the LLM knows to correct (not continue).
100
+
101
+ ## 6) Keep Outputs Small by Default (Prevent Truncation)
102
+
103
+ Large outputs cause:
104
+ - truncation (the model misses the answer),
105
+ - follow-up calls,
106
+ - and sometimes tool-call loops.
107
+
108
+ Do:
109
+ - omit base64-encoded blobs by default (make them opt-in),
110
+ - provide `-o/--output` style file outputs for large bodies,
111
+ - include lightweight metadata (status code, headers, elapsed time).
112
+
113
+ ## 7) Add Tests that Simulate “LLM Mistakes”
114
+
115
+ Every new endpoint should include tests that cover:
116
+ - structured payload success (`{ url, method }`),
117
+ - curl-style args success (`{ args: [...] }`),
118
+ - invalid shape failure (missing URL),
119
+ - “tool not found” suggestion behavior (server-side).
120
+
121
+ Tests belong next to the server/tool code (Bun tests under `api/`).
122
+
123
+ ## 8) Endpoint Implementation Checklist
124
+
125
+ When adding `root.namespace.tool`:
126
+ - Add it under an explicit namespace (`net.*`, `projects.*`, etc.), not the root.
127
+ - Add/adjust `TOOL_INPUT_SCHEMA_OVERRIDES[toolName]` with examples.
128
+ - Ensure tool access is correct (read vs write vs admin).
129
+ - Ensure agent configs include the root endpoint in `--allowed-root-endpoints` when needed.
130
+ - Consider `directTools` for high-frequency tools.