fa-mcp-sdk 0.11.2 → 0.11.8
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/cli-template/AGENTS.md +1 -0
- package/cli-template/FA-MCP-SDK-DOC/00-FA-MCP-SDK-index.md +1 -0
- package/cli-template/FA-MCP-SDK-DOC/12-implementation-standard.md +1148 -0
- package/cli-template/package.json +1 -1
- package/dist/core/web/server-http.d.ts.map +1 -1
- package/dist/core/web/server-http.js +171 -1
- package/dist/core/web/server-http.js.map +1 -1
- package/dist/core/web/static/agent-tester/script.js +13 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1148 @@
|
|
|
1
|
+
# Corporate MCP Server Implementation Standard
|
|
2
|
+
|
|
3
|
+
| Parameter | Value |
|
|
4
|
+
|----------------------------|------------------------------------|
|
|
5
|
+
| Version | 1.2 |
|
|
6
|
+
| Status | Active |
|
|
7
|
+
| Date | 2026-06-03 |
|
|
8
|
+
| Scope | All internal company MCP servers |
|
|
9
|
+
| Base MCP | MCP 2025-11-25 |
|
|
10
|
+
| Starter SDK (optional) | `fa-mcp-sdk` |
|
|
11
|
+
| Owner | AI/MCP Platform team |
|
|
12
|
+
|
|
13
|
+
> This document is the English translation of the corporate implementation standard. It restates the
|
|
14
|
+
> explicit MCP 2025-11-25 requirements plus the corporate Avatar / AI Platform profile in a single
|
|
15
|
+
> self-contained document. Version 1.2 adds the side-effect tools and risk-level rules and fixes the
|
|
16
|
+
> `-32007` error-code inconsistency.
|
|
17
|
+
|
|
18
|
+
## Table of Contents
|
|
19
|
+
|
|
20
|
+
1. [Purpose and scope](#1-purpose-and-scope)
|
|
21
|
+
2. [Terminology and requirement levels](#2-terminology-and-requirement-levels)
|
|
22
|
+
3. [Compatibility with MCP 2025-11-25](#3-compatibility-with-mcp-2025-11-25)
|
|
23
|
+
4. [MCP protocol versioning](#4-mcp-protocol-versioning)
|
|
24
|
+
5. [Transports](#5-transports)
|
|
25
|
+
6. [HTTP interface](#6-http-interface)
|
|
26
|
+
7. [Authentication and authorization](#7-authentication-and-authorization)
|
|
27
|
+
8. [MCP methods and lifecycle](#8-mcp-methods-and-lifecycle)
|
|
28
|
+
9. [Tools: external contract](#9-tools-external-contract)
|
|
29
|
+
10. [Prompts: external contract](#10-prompts-external-contract)
|
|
30
|
+
11. [Resources: external contract](#11-resources-external-contract)
|
|
31
|
+
12. [Result format](#12-result-format)
|
|
32
|
+
13. [Error format](#13-error-format)
|
|
33
|
+
14. [Limits and protection](#14-limits-and-protection)
|
|
34
|
+
15. [Observability](#15-observability)
|
|
35
|
+
16. [Health and readiness](#16-health-and-readiness)
|
|
36
|
+
17. [Contract stability and deprecation](#17-contract-stability-and-deprecation)
|
|
37
|
+
18. [Compliance checklist](#18-compliance-checklist)
|
|
38
|
+
19. [Appendix A. Auth profile](#appendix-a-auth-profile)
|
|
39
|
+
20. [Appendix B. Error codes](#appendix-b-error-codes)
|
|
40
|
+
21. [Appendix C. Input / output summary table](#appendix-c-input--output-summary-table)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 1. Purpose and scope
|
|
45
|
+
|
|
46
|
+
This document defines the corporate profile of an MCP server developed in-house. It builds on the common
|
|
47
|
+
MCP 2025-11-25 protocol and adds internal Avatar / AI Platform requirements for security, network
|
|
48
|
+
interface, naming, observability, and operational contracts.
|
|
49
|
+
|
|
50
|
+
The document covers:
|
|
51
|
+
|
|
52
|
+
- transport and network interface;
|
|
53
|
+
- authentication and authorization;
|
|
54
|
+
- the set of published tools, prompts, and resources;
|
|
55
|
+
- result and error formats;
|
|
56
|
+
- operational requirements (health, observability, limits);
|
|
57
|
+
- rules for evolving the public contract.
|
|
58
|
+
|
|
59
|
+
The internal implementation, language, framework, and architecture are **not regulated**. A server may be
|
|
60
|
+
built on any technology stack as long as it fully complies with the external requirements of this standard.
|
|
61
|
+
To speed up the start, a team MAY use `fa-mcp-sdk`, the official MCP SDK, or its own implementation.
|
|
62
|
+
|
|
63
|
+
The standard applies to servers exposed to:
|
|
64
|
+
|
|
65
|
+
- internal company AI agents;
|
|
66
|
+
- internal services via MCP clients;
|
|
67
|
+
- partner environments, if the server is published beyond the perimeter.
|
|
68
|
+
|
|
69
|
+
The standard **does not apply** to local experimental servers without external consumers.
|
|
70
|
+
|
|
71
|
+
## 2. Terminology and requirement levels
|
|
72
|
+
|
|
73
|
+
The RFC 2119 keywords are used:
|
|
74
|
+
|
|
75
|
+
| Term | Meaning |
|
|
76
|
+
| --------------- | -------------------------------------------------------- |
|
|
77
|
+
| MUST | Hard requirement. Non-compliance = acceptance blocker. |
|
|
78
|
+
| SHOULD | Recommended. A deviation requires a justification in the README. |
|
|
79
|
+
| MAY | Allowed at the team's discretion. |
|
|
80
|
+
|
|
81
|
+
Other terms:
|
|
82
|
+
|
|
83
|
+
- **Public contract** — the set of all externally visible elements of the server, listed in §17.
|
|
84
|
+
- **Breaking change** — any change to the public contract that breaks existing clients.
|
|
85
|
+
- **Starter SDK** — one of the allowed ways to speed up the start of implementation; it is not part of the
|
|
86
|
+
public contract and does not constrain the language or internal architecture of the server.
|
|
87
|
+
- **Corporate profile** — additional company requirements on top of common MCP. If a requirement is marked
|
|
88
|
+
as corporate, it is not a universal MCP requirement, but it is mandatory for internal servers.
|
|
89
|
+
|
|
90
|
+
## 3. Compatibility with MCP 2025-11-25
|
|
91
|
+
|
|
92
|
+
This standard is compatible with MCP 2025-11-25 and must be treated as a corporate profile on top of the
|
|
93
|
+
common protocol.
|
|
94
|
+
|
|
95
|
+
Base MCP 2025-11-25 requirements:
|
|
96
|
+
|
|
97
|
+
- JSON-RPC 2.0 is used for all MCP messages;
|
|
98
|
+
- server and client go through the `initialize` / `initialized` lifecycle;
|
|
99
|
+
- both parties declare and respect negotiated capabilities;
|
|
100
|
+
- standard transports: `stdio` and Streamable HTTP;
|
|
101
|
+
- the HTTP transport uses a single MCP endpoint, usually `/mcp`, with `POST` and an optional `GET` for the
|
|
102
|
+
SSE stream;
|
|
103
|
+
- `MCP-Protocol-Version` is sent on subsequent HTTP requests after negotiation;
|
|
104
|
+
- `MCP-Session-Id` is used only as a session identifier and does not replace authentication;
|
|
105
|
+
- `tools`, `prompts`, `resources`, `logging`, `completions`, `tasks` are used only if the capability has
|
|
106
|
+
been declared and negotiated.
|
|
107
|
+
|
|
108
|
+
Corporate extensions of this standard:
|
|
109
|
+
|
|
110
|
+
- mandatory authentication for internal HTTP / Streamable HTTP MCP servers;
|
|
111
|
+
- a corporate JWT / opaque token profile for internal environments;
|
|
112
|
+
- preserving snake_case tool names;
|
|
113
|
+
- recommended prompts `agent_brief` and `agent_prompt` for Avatar routing;
|
|
114
|
+
- corporate URI schemes `use://`, `project://`, `doc://`;
|
|
115
|
+
- mandatory limits, observability, health/readiness, and CHANGELOG.
|
|
116
|
+
|
|
117
|
+
If a server is published for generic MCP clients beyond the internal perimeter, it SHOULD follow common
|
|
118
|
+
MCP 2025-11-25 for authorization discovery, Streamable HTTP, and the error model. If a server is available
|
|
119
|
+
only to internal Avatar clients, the corporate profile is allowed, provided it is explicitly documented in
|
|
120
|
+
the README and `use://auth`.
|
|
121
|
+
|
|
122
|
+
## 4. MCP protocol versioning
|
|
123
|
+
|
|
124
|
+
The server MUST:
|
|
125
|
+
|
|
126
|
+
- declare the supported MCP protocol version in the `initialize` response;
|
|
127
|
+
- support MCP 2025-11-25 for new HTTP / Streamable HTTP servers unless the README states another version;
|
|
128
|
+
- return a standard `initialize` error on version mismatch instead of crashing;
|
|
129
|
+
- for the HTTP transport, accept `MCP-Protocol-Version` on subsequent requests and return HTTP 400 for an
|
|
130
|
+
explicitly unsupported version.
|
|
131
|
+
|
|
132
|
+
The server MUST maintain its own semver versioning:
|
|
133
|
+
|
|
134
|
+
| Change | Version bump |
|
|
135
|
+
| --------------------------------------- | ------------ |
|
|
136
|
+
| Breaking change to the public contract | MAJOR |
|
|
137
|
+
| New tool / prompt / resource | MINOR |
|
|
138
|
+
| Bugfix without a contract change | PATCH |
|
|
139
|
+
|
|
140
|
+
The server version MUST be available through:
|
|
141
|
+
|
|
142
|
+
- the `/health` response (the `version` field);
|
|
143
|
+
- `serverInfo.version` in `initialize.result`;
|
|
144
|
+
- the `project://version` resource (SHOULD).
|
|
145
|
+
|
|
146
|
+
## 5. Transports
|
|
147
|
+
|
|
148
|
+
The server MUST support at least one transport. Allowed transports:
|
|
149
|
+
|
|
150
|
+
| Transport | Purpose | When mandatory |
|
|
151
|
+
| ----------------- | ---------------------------------------- | -------------- |
|
|
152
|
+
| `stdio` | Local launch (Claude Desktop, etc.) | if the server targets a desktop agent |
|
|
153
|
+
| `streamable_http` | Corporate network access per MCP 2025-11-25 | for all new network MCP servers (MUST) |
|
|
154
|
+
| `legacy_http_sse` | Compatibility with the old HTTP+SSE transport | MAY for existing clients |
|
|
155
|
+
| custom | Specialized transport | MAY with explicit documentation |
|
|
156
|
+
|
|
157
|
+
The semantics of MCP calls MUST be identical across all declared transports.
|
|
158
|
+
|
|
159
|
+
For `stdio`:
|
|
160
|
+
|
|
161
|
+
- the server reads JSON-RPC messages from `stdin` and writes only valid MCP messages to `stdout`;
|
|
162
|
+
- logs are allowed only on `stderr`;
|
|
163
|
+
- messages are newline-delimited and MUST NOT contain an embedded newline.
|
|
164
|
+
|
|
165
|
+
For `streamable_http`:
|
|
166
|
+
|
|
167
|
+
- the server MUST expose a single MCP endpoint, usually `/mcp`;
|
|
168
|
+
- the client sends each JSON-RPC message as a separate `POST /mcp`;
|
|
169
|
+
- the server MAY use an SSE stream via `GET /mcp` or via a `POST /mcp` response with
|
|
170
|
+
`Content-Type: text/event-stream`;
|
|
171
|
+
- a separate `/sse` endpoint is NOT the primary transport of MCP 2025-11-25 and is allowed only as a legacy
|
|
172
|
+
compatibility path.
|
|
173
|
+
|
|
174
|
+
## 6. HTTP interface
|
|
175
|
+
|
|
176
|
+
For servers with Streamable HTTP:
|
|
177
|
+
|
|
178
|
+
| Endpoint | Method | Level | Purpose |
|
|
179
|
+
| ---------- | ------ | ----- | ------------------------------------ |
|
|
180
|
+
| `/mcp` | POST | MUST | Main MCP endpoint (JSON-RPC 2.0) |
|
|
181
|
+
| `/mcp` | GET | MAY | SSE stream from server to client; return 405 if not supported |
|
|
182
|
+
| `/mcp` | DELETE | MAY | Explicit MCP session termination |
|
|
183
|
+
| `/health` | GET | MUST | Liveness check |
|
|
184
|
+
| `/ready` | GET | SHOULD | Readiness check |
|
|
185
|
+
| `/sse` | GET | MAY, legacy only | Old HTTP+SSE transport for backward compatibility |
|
|
186
|
+
| `/` | GET | SHOULD | Service HTML page / redirect to documentation |
|
|
187
|
+
|
|
188
|
+
Requirements for `POST /mcp`:
|
|
189
|
+
|
|
190
|
+
- `Content-Type: application/json` on input;
|
|
191
|
+
- `Accept` MUST include `application/json` and `text/event-stream`;
|
|
192
|
+
- the body is a single valid JSON-RPC 2.0 request, notification, or response;
|
|
193
|
+
- if the input is a request, the server returns a single JSON response (`application/json`) or an SSE
|
|
194
|
+
stream (`text/event-stream`);
|
|
195
|
+
- if the input is a notification or response and the server accepted the message, the server returns
|
|
196
|
+
HTTP 202 with no body;
|
|
197
|
+
- the server MUST respond with a valid JSON-RPC error rather than HTML or plain text on a protocol-level
|
|
198
|
+
failure.
|
|
199
|
+
|
|
200
|
+
Requirements for `GET /mcp`:
|
|
201
|
+
|
|
202
|
+
- `Accept` MUST include `text/event-stream`;
|
|
203
|
+
- if the SSE stream is supported, the server returns `Content-Type: text/event-stream`;
|
|
204
|
+
- if the SSE stream is not supported, the server returns HTTP 405 Method Not Allowed;
|
|
205
|
+
- the server MUST NOT send a JSON-RPC response on an independent GET stream, except for the resume scenario
|
|
206
|
+
via `Last-Event-ID`.
|
|
207
|
+
|
|
208
|
+
MCP HTTP headers:
|
|
209
|
+
|
|
210
|
+
| Header | Level | Behavior |
|
|
211
|
+
| ------ | ----- | -------- |
|
|
212
|
+
| `MCP-Protocol-Version` | MUST for HTTP after `initialize` | The protocol version negotiated in the lifecycle, e.g. `2025-11-25` |
|
|
213
|
+
| `MCP-Session-Id` | MUST if the server issued a session id | Sent on all subsequent HTTP requests of this MCP session |
|
|
214
|
+
| `Accept` | MUST | `application/json, text/event-stream` for POST; `text/event-stream` for GET |
|
|
215
|
+
| `Content-Type` | MUST for POST | `application/json` |
|
|
216
|
+
| `Last-Event-ID` | MAY | Used by the client to resume an SSE stream |
|
|
217
|
+
|
|
218
|
+
Session management:
|
|
219
|
+
|
|
220
|
+
- the server MAY issue an `MCP-Session-Id` in the HTTP response to `initialize`;
|
|
221
|
+
- the session id MUST be globally unique, cryptographically strong, and contain only visible ASCII;
|
|
222
|
+
- if the server requires `MCP-Session-Id`, requests without it after initialization must receive HTTP 400;
|
|
223
|
+
- if the session has expired, a request with that session must receive HTTP 404;
|
|
224
|
+
- the session id MUST NOT be used as proof of identity or as a replacement for `Authorization`.
|
|
225
|
+
|
|
226
|
+
CORS / Origin:
|
|
227
|
+
|
|
228
|
+
- the server MUST explicitly configure the list of allowed origins;
|
|
229
|
+
- `*` is forbidden in production;
|
|
230
|
+
- preflight OPTIONS MUST be handled correctly;
|
|
231
|
+
- the server MUST validate `Origin` on HTTP / Streamable HTTP requests if the header is present;
|
|
232
|
+
- on an invalid `Origin`, the server MUST return HTTP 403;
|
|
233
|
+
- local HTTP MCP servers SHOULD bind to `127.0.0.1` rather than `0.0.0.0`.
|
|
234
|
+
|
|
235
|
+
## 7. Authentication and authorization
|
|
236
|
+
|
|
237
|
+
### 7.1. General rules
|
|
238
|
+
|
|
239
|
+
| Requirement | Level |
|
|
240
|
+
| --------------------------------------------------------- | ----- |
|
|
241
|
+
| HTTP / Streamable HTTP without authentication | FORBIDDEN for internal servers |
|
|
242
|
+
| Passing secrets in the query string | FORBIDDEN |
|
|
243
|
+
| Passing secrets in logs / traces | FORBIDDEN |
|
|
244
|
+
| Anonymous access to `tools/list`, `prompts/list` | MAY (if explicitly decided) |
|
|
245
|
+
| Authentication on `tools/call`, `prompts/get`, `resources/read` | MUST |
|
|
246
|
+
|
|
247
|
+
### 7.2. Supported corporate schemes
|
|
248
|
+
|
|
249
|
+
| Scheme | Use | Level |
|
|
250
|
+
| ----------------- | ------------------------------------- | ----- |
|
|
251
|
+
| `Bearer` (JWT) | Primary for service-to-service and user-context | MUST support |
|
|
252
|
+
| `Bearer` (opaque) | Long-lived server tokens from the secret manager | MAY |
|
|
253
|
+
| `Basic` | Service scenarios and admin endpoints only | MAY |
|
|
254
|
+
| Custom | Only with explicit documentation in the README + the `use://http-headers` resource | MAY |
|
|
255
|
+
|
|
256
|
+
Header:
|
|
257
|
+
|
|
258
|
+
```http
|
|
259
|
+
Authorization: Bearer <token>
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
The detailed corporate JWT profile is in [Appendix A](#appendix-a-auth-profile).
|
|
263
|
+
|
|
264
|
+
### 7.3. Compatibility with OAuth MCP authorization
|
|
265
|
+
|
|
266
|
+
If the MCP server is published for generic MCP clients and uses authorization, it SHOULD follow the common
|
|
267
|
+
MCP authorization profile:
|
|
268
|
+
|
|
269
|
+
- the MCP server acts as an OAuth 2.1 resource server;
|
|
270
|
+
- the server publishes OAuth 2.0 Protected Resource Metadata
|
|
271
|
+
(`/.well-known/oauth-protected-resource`);
|
|
272
|
+
- the authorization server publishes OAuth 2.0 Authorization Server Metadata
|
|
273
|
+
(`/.well-known/oauth-authorization-server`);
|
|
274
|
+
- the HTTP 401 response contains `WWW-Authenticate` pointing to the resource metadata;
|
|
275
|
+
- the client uses the `resource` parameter on authorization/token requests;
|
|
276
|
+
- the server validates that the access token was issued specifically for this MCP server audience;
|
|
277
|
+
- token passthrough is forbidden: the MCP server MUST NOT forward downstream the same access token it
|
|
278
|
+
received from the MCP client if the downstream is a separate resource server.
|
|
279
|
+
|
|
280
|
+
Internal Avatar servers MAY use the corporate JWT / opaque token profile without full OAuth discovery if
|
|
281
|
+
this is explicitly stated in the README and `use://auth`.
|
|
282
|
+
|
|
283
|
+
### 7.4. Authentication responses
|
|
284
|
+
|
|
285
|
+
| Situation | HTTP | Header |
|
|
286
|
+
| ---------------------------------- | ---- | ----------------------------------------------- |
|
|
287
|
+
| Token missing | 401 | `WWW-Authenticate: Bearer realm="<service>"` or an OAuth resource metadata challenge |
|
|
288
|
+
| Token invalid / expired | 401 | `WWW-Authenticate: Bearer error="invalid_token"` |
|
|
289
|
+
| Token valid, no rights for operation | 403 | — |
|
|
290
|
+
|
|
291
|
+
Authentication errors at the HTTP layer are returned as HTTP 401/403. If the error is already inside
|
|
292
|
+
JSON-RPC processing, the server MAY return a JSON-RPC error in the §13 format, but it must not override the
|
|
293
|
+
standard JSON-RPC codes for transport auth.
|
|
294
|
+
|
|
295
|
+
### 7.5. Authorization
|
|
296
|
+
|
|
297
|
+
The server MUST support at least **boolean authorization** ("allowed / not allowed"). Fine-grained
|
|
298
|
+
authorization (per-tool, per-resource) is SHOULD.
|
|
299
|
+
|
|
300
|
+
If the server uses roles / scopes from a JWT, the list of claims used MUST be documented in
|
|
301
|
+
`use://http-headers` or a separate `use://auth` resource.
|
|
302
|
+
|
|
303
|
+
## 8. MCP methods and lifecycle
|
|
304
|
+
|
|
305
|
+
### 8.1. Lifecycle
|
|
306
|
+
|
|
307
|
+
The MCP lifecycle MUST be executed in the following order:
|
|
308
|
+
|
|
309
|
+
1. The client sends `initialize` with `protocolVersion`, `capabilities`, `clientInfo`.
|
|
310
|
+
2. The server responds with `initialize.result` with `protocolVersion`, `capabilities`, `serverInfo`.
|
|
311
|
+
3. The client sends `notifications/initialized`.
|
|
312
|
+
4. After that, both parties exchange normal MCP requests/notifications only within the negotiated
|
|
313
|
+
capabilities.
|
|
314
|
+
|
|
315
|
+
Until initialization completes, both client and server SHOULD NOT send normal requests, except `ping` and
|
|
316
|
+
allowed service notifications.
|
|
317
|
+
|
|
318
|
+
### 8.2. Capability negotiation
|
|
319
|
+
|
|
320
|
+
The server MUST declare the capabilities it actually supports:
|
|
321
|
+
|
|
322
|
+
| Capability | Level | Purpose |
|
|
323
|
+
| ---------- | ----- | ------- |
|
|
324
|
+
| `tools` | MUST if the server publishes tools | Callable tools |
|
|
325
|
+
| `prompts` | MAY | Prompt templates |
|
|
326
|
+
| `resources` | MAY | Readable resources |
|
|
327
|
+
| `logging` | SHOULD | Structured log messages |
|
|
328
|
+
| `completions` | MAY | Autocomplete for arguments |
|
|
329
|
+
| `tasks` | MAY | Task-augmented execution, MCP 2025-11-25 |
|
|
330
|
+
| `experimental` | MAY | Non-standard extensions |
|
|
331
|
+
|
|
332
|
+
If a capability is not declared and negotiated, the server MUST NOT require the client to support the
|
|
333
|
+
corresponding methods.
|
|
334
|
+
|
|
335
|
+
### 8.3. MCP methods
|
|
336
|
+
|
|
337
|
+
The server MUST accept the standard MCP methods within the declared capabilities:
|
|
338
|
+
|
|
339
|
+
| Method | Level | Purpose |
|
|
340
|
+
| ----------------- | -------------------------------- | ----------------------------------- |
|
|
341
|
+
| `initialize` | MUST | Handshake, version, capabilities |
|
|
342
|
+
| `notifications/initialized` | MUST accept after `initialize` | Completes initialization |
|
|
343
|
+
| `tools/list` | MUST if the server publishes tools | List of tools |
|
|
344
|
+
| `tools/call` | MUST if the server publishes tools | Tool invocation |
|
|
345
|
+
| `prompts/list` | MUST if the server publishes prompts | List of prompts |
|
|
346
|
+
| `prompts/get` | MUST if the server publishes prompts | Get a prompt |
|
|
347
|
+
| `resources/list` | MUST if the server publishes resources | List of resources |
|
|
348
|
+
| `resources/read` | MUST if the server publishes resources | Read a resource |
|
|
349
|
+
| `resources/templates/list` | MAY if the server publishes template resources | List of resource templates |
|
|
350
|
+
| `resources/subscribe` | MAY if subscriptions are supported | Subscribe to resource changes |
|
|
351
|
+
| `ping` | SHOULD | Keepalive |
|
|
352
|
+
|
|
353
|
+
The server MUST NOT:
|
|
354
|
+
|
|
355
|
+
- register custom method names instead of the standard MCP ones;
|
|
356
|
+
- silently ignore an unknown method — it must return `-32601 Method not found`;
|
|
357
|
+
- use capability-specific methods without declaring the corresponding capability.
|
|
358
|
+
|
|
359
|
+
### 8.4. Pagination
|
|
360
|
+
|
|
361
|
+
The `tools/list`, `prompts/list`, `resources/list`, and `resources/templates/list` methods MUST support MCP
|
|
362
|
+
pagination if the potential list can be large.
|
|
363
|
+
|
|
364
|
+
Rules:
|
|
365
|
+
|
|
366
|
+
- the request MAY contain `params.cursor`;
|
|
367
|
+
- the response MAY contain `nextCursor`;
|
|
368
|
+
- the client SHOULD keep reading while `nextCursor` is present;
|
|
369
|
+
- the server MUST NOT change the order of items between pages within a single listing without a reason.
|
|
370
|
+
|
|
371
|
+
### 8.5. Cancellation
|
|
372
|
+
|
|
373
|
+
MCP supports cancellation of in-progress requests via `notifications/cancelled`.
|
|
374
|
+
|
|
375
|
+
The server SHOULD:
|
|
376
|
+
|
|
377
|
+
- accept `notifications/cancelled` for long-running operations;
|
|
378
|
+
- stop executing the cancelled request when it is safe to do so;
|
|
379
|
+
- release resources;
|
|
380
|
+
- log the reason without user secrets;
|
|
381
|
+
- not send a response for a request whose processing was cancelled before completion.
|
|
382
|
+
|
|
383
|
+
The client MUST NOT cancel `initialize`.
|
|
384
|
+
|
|
385
|
+
### 8.6. Progress
|
|
386
|
+
|
|
387
|
+
For long-running operations, the server MAY send `notifications/progress` if the request contains
|
|
388
|
+
`_meta.progressToken`.
|
|
389
|
+
|
|
390
|
+
Rules:
|
|
391
|
+
|
|
392
|
+
- `progressToken` must reference only an active request;
|
|
393
|
+
- the `progress` value must increase monotonically;
|
|
394
|
+
- `total` and `message` are optional;
|
|
395
|
+
- progress notifications must stop after the request completes;
|
|
396
|
+
- the rate of progress events must be limited so as not to overload the client.
|
|
397
|
+
|
|
398
|
+
### 8.7. Tasks
|
|
399
|
+
|
|
400
|
+
MCP 2025-11-25 introduces task-augmented execution as an additional capability. The server MAY declare the
|
|
401
|
+
`tasks` capability and `execution.taskSupport` on individual tools if it supports long-lived or managed
|
|
402
|
+
tasks.
|
|
403
|
+
|
|
404
|
+
If tasks are not supported, the server MUST NOT declare the `tasks` capability and must use the regular
|
|
405
|
+
`tools/call` flow.
|
|
406
|
+
|
|
407
|
+
## 9. Tools: external contract
|
|
408
|
+
|
|
409
|
+
### 9.1. Tool declaration
|
|
410
|
+
|
|
411
|
+
Each tool in `tools/list` MUST contain:
|
|
412
|
+
|
|
413
|
+
| Field | Type | Level | Requirement |
|
|
414
|
+
| ------------- | ------ | ------- | --------------------------------------- |
|
|
415
|
+
| `name` | string | MUST | `^[a-z][a-z0-9_]{1,63}$`, snake_case, English. This corporate constraint is stricter than common MCP. |
|
|
416
|
+
| `description` | string | MUST | Concise description + constraints + side effects + dangerous actions |
|
|
417
|
+
| `inputSchema` | object | MUST | Valid JSON Schema 2020-12 by default |
|
|
418
|
+
| `title` | string | SHOULD | Human-readable tool name for UI |
|
|
419
|
+
| `outputSchema` | object | SHOULD if the tool returns `structuredContent` | JSON Schema of the result |
|
|
420
|
+
| `annotations` | object | MAY | Hints to the client (`readOnlyHint`, etc.) |
|
|
421
|
+
| `icons` | array | MAY | Icons for UI |
|
|
422
|
+
| `execution` | object | MAY | Execution metadata, including `taskSupport` |
|
|
423
|
+
|
|
424
|
+
The snake_case corporate rule is preserved deliberately. It narrows common MCP 2025-11-25, which also
|
|
425
|
+
allows `-`, `.`, uppercase, and camelCase.
|
|
426
|
+
|
|
427
|
+
### 9.2. `inputSchema` requirements
|
|
428
|
+
|
|
429
|
+
- JSON Schema 2020-12 is used by default.
|
|
430
|
+
- If draft-07 is used, the `$schema` field MUST be specified explicitly.
|
|
431
|
+
- `inputSchema` MUST be a valid JSON Schema object, not `null`.
|
|
432
|
+
- `type: "object"` at the top level — SHOULD.
|
|
433
|
+
- explicit `properties` — SHOULD;
|
|
434
|
+
- explicit `required` — SHOULD, even if empty;
|
|
435
|
+
- `additionalProperties: false` — SHOULD;
|
|
436
|
+
- a `description` for each field — SHOULD.
|
|
437
|
+
|
|
438
|
+
Recommended schema for a tool without parameters:
|
|
439
|
+
|
|
440
|
+
```json
|
|
441
|
+
{
|
|
442
|
+
"type": "object",
|
|
443
|
+
"additionalProperties": false
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### 9.3. Side effects and risk level
|
|
448
|
+
|
|
449
|
+
This section is a corporate requirement on top of common MCP.
|
|
450
|
+
|
|
451
|
+
| Requirement | Level |
|
|
452
|
+
| --------------------------------------------------------------------- | ----- |
|
|
453
|
+
| A mutating tool MUST explicitly state its side effects in `description`. | MUST |
|
|
454
|
+
| A mutating tool MUST declare a risk level (for example `low` / `medium` / `high`). | MUST |
|
|
455
|
+
| Domain errors that the model can correct are returned as `result.isError=true`. | SHOULD |
|
|
456
|
+
|
|
457
|
+
The risk level MAY be expressed through the standard `annotations` field (for example `readOnlyHint`,
|
|
458
|
+
`destructiveHint`, `idempotentHint`) and MUST additionally be stated in human-readable form in
|
|
459
|
+
`description` so that a routing agent can reason about it without parsing annotations.
|
|
460
|
+
|
|
461
|
+
For tools with external side effects, the following MUST also be documented (in `description`, the README,
|
|
462
|
+
or a dedicated resource):
|
|
463
|
+
|
|
464
|
+
- an idempotency key, or the reason idempotency is absent;
|
|
465
|
+
- the retry policy;
|
|
466
|
+
- the timeout behavior;
|
|
467
|
+
- the audit event emitted by the operation;
|
|
468
|
+
- the approval requirement for risky actions.
|
|
469
|
+
|
|
470
|
+
A read-only tool SHOULD set `readOnlyHint: true` so that clients can treat it as safe to call without
|
|
471
|
+
confirmation.
|
|
472
|
+
|
|
473
|
+
### 9.4. `tools/call` behavior
|
|
474
|
+
|
|
475
|
+
| Situation | Response |
|
|
476
|
+
| --------------------------------------- | ------------------------------------------- |
|
|
477
|
+
| Malformed JSON-RPC or invalid `tools/call.params` structure | JSON-RPC error `-32602 Invalid params` |
|
|
478
|
+
| Unknown `params.name` | JSON-RPC error `-32602 Invalid params` with the safe message `Unknown tool` |
|
|
479
|
+
| Business logic / domain validation error the model can fix | `result.isError=true` with actionable `content` |
|
|
480
|
+
| Internal JSON-RPC layer error | JSON-RPC error `-32603 Internal error` without a stacktrace |
|
|
481
|
+
| Success | `result` with `content`, `structuredContent`, or both formats |
|
|
482
|
+
|
|
483
|
+
The server MUST validate `arguments` against `inputSchema` before reaching the domain. Errors that relate
|
|
484
|
+
to the shape of the JSON-RPC request are returned as a JSON-RPC error. Tool execution errors and domain
|
|
485
|
+
errors are returned as a tool execution result with `isError: true` if that helps the model adjust the
|
|
486
|
+
request.
|
|
487
|
+
|
|
488
|
+
Example of a tool execution error:
|
|
489
|
+
|
|
490
|
+
```json
|
|
491
|
+
{
|
|
492
|
+
"jsonrpc": "2.0",
|
|
493
|
+
"id": 4,
|
|
494
|
+
"result": {
|
|
495
|
+
"content": [
|
|
496
|
+
{ "type": "text", "text": "Invalid date: value must be in the future." }
|
|
497
|
+
],
|
|
498
|
+
"isError": true
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### 9.5. Structured output
|
|
504
|
+
|
|
505
|
+
If a tool declares `outputSchema`, the server MUST return `structuredContent` that conforms to that schema.
|
|
506
|
+
|
|
507
|
+
For backward compatibility, a tool returning `structuredContent` SHOULD also return the serialized JSON in
|
|
508
|
+
`content` as `TextContent`.
|
|
509
|
+
|
|
510
|
+
## 10. Prompts: external contract
|
|
511
|
+
|
|
512
|
+
### 10.1. Prompt support
|
|
513
|
+
|
|
514
|
+
Prompts are an optional MCP capability. The server MAY publish no prompts. If the server publishes prompts,
|
|
515
|
+
it MUST declare the `prompts` capability and implement `prompts/list` and `prompts/get`.
|
|
516
|
+
|
|
517
|
+
### 10.2. Recommended Avatar profile prompts
|
|
518
|
+
|
|
519
|
+
For servers that participate in agent routing, the following SHOULD be published:
|
|
520
|
+
|
|
521
|
+
| Name | Level | Purpose |
|
|
522
|
+
| --------------- | ------- | ------------------------------------------- |
|
|
523
|
+
| `agent_brief` | SHOULD | Short description for agent routing (level 1) |
|
|
524
|
+
| `agent_prompt` | SHOULD | Full operating instructions (level 2) |
|
|
525
|
+
|
|
526
|
+
These prompts are an Avatar-profile corporate recommendation and are not mandatory names of common MCP.
|
|
527
|
+
|
|
528
|
+
### 10.3. `agent_brief` content
|
|
529
|
+
|
|
530
|
+
SHOULD describe:
|
|
531
|
+
|
|
532
|
+
- the server's domain;
|
|
533
|
+
- when to select this server;
|
|
534
|
+
- when **not** to select it;
|
|
535
|
+
- key constraints (read-only, data domain, etc.).
|
|
536
|
+
|
|
537
|
+
Size — SHOULD NOT exceed 2 KB of text.
|
|
538
|
+
|
|
539
|
+
### 10.4. `agent_prompt` content
|
|
540
|
+
|
|
541
|
+
SHOULD contain:
|
|
542
|
+
|
|
543
|
+
- instructions for using each tool;
|
|
544
|
+
- domain and security constraints;
|
|
545
|
+
- the expected format of the agent's responses;
|
|
546
|
+
- examples (SHOULD).
|
|
547
|
+
|
|
548
|
+
### 10.5. Parameterized prompts
|
|
549
|
+
|
|
550
|
+
If a prompt accepts arguments, they MUST be described in `prompts/list` via the standard MCP `arguments`
|
|
551
|
+
field.
|
|
552
|
+
|
|
553
|
+
Important: `prompts/list.result.prompts[].arguments` is not a full JSON Schema. It is an array of
|
|
554
|
+
descriptors of the form:
|
|
555
|
+
|
|
556
|
+
```json
|
|
557
|
+
[
|
|
558
|
+
{
|
|
559
|
+
"name": "code",
|
|
560
|
+
"description": "The code to review",
|
|
561
|
+
"required": true
|
|
562
|
+
}
|
|
563
|
+
]
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
Complex prompt-argument validation rules SHOULD be documented in `description`, the README, or a separate
|
|
567
|
+
resource.
|
|
568
|
+
|
|
569
|
+
A prompt definition MAY contain `title`, `description`, `icons`, and `arguments` per MCP 2025-11-25.
|
|
570
|
+
|
|
571
|
+
## 11. Resources: external contract
|
|
572
|
+
|
|
573
|
+
### 11.1. URI schemes
|
|
574
|
+
|
|
575
|
+
Two classes of schemes are used.
|
|
576
|
+
|
|
577
|
+
**1. Service-specific scheme (MUST).** For resources belonging to a specific server, a unique scheme is
|
|
578
|
+
used that matches the service name in the registry:
|
|
579
|
+
|
|
580
|
+
```
|
|
581
|
+
<service-name>://<path>
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
Example: `staff://agent/brief`. The server MUST respond only to its own scheme and MUST NOT register
|
|
585
|
+
others.
|
|
586
|
+
|
|
587
|
+
**2. Reserved cross-service schemes (standard for the Avatar profile).** This standard reserves the
|
|
588
|
+
following global schemes for uniform meta-information; their semantics are fixed and identical across
|
|
589
|
+
internal servers:
|
|
590
|
+
|
|
591
|
+
| Scheme | Purpose |
|
|
592
|
+
| ------------ | --------------------------------------------------------- |
|
|
593
|
+
| `use://` | Instructions for using the server (headers, auth, etc.) |
|
|
594
|
+
| `project://` | Server meta-information (version, name, owner) |
|
|
595
|
+
| `doc://` | Server documentation (README, etc.) |
|
|
596
|
+
|
|
597
|
+
The server MUST implement those `use://` / `project://` / `doc://` resources required by §11.2. Inventing
|
|
598
|
+
your own paths under these schemes beyond this standard is FORBIDDEN.
|
|
599
|
+
|
|
600
|
+
### 11.2. Recommended minimum resources
|
|
601
|
+
|
|
602
|
+
| URI | Level | Purpose |
|
|
603
|
+
| -------------------------------- | ------- | --------------------------------------------- |
|
|
604
|
+
| `<service-name>://agent/brief` | SHOULD | Mirror of the `agent_brief` prompt |
|
|
605
|
+
| `<service-name>://agent/prompt` | SHOULD | Mirror of the `agent_prompt` prompt |
|
|
606
|
+
| `use://http-headers` | MUST if there are non-standard headers | Description of all expected HTTP headers |
|
|
607
|
+
| `use://auth` | SHOULD | Description of the authentication scheme and claims |
|
|
608
|
+
| `project://version` | SHOULD | Current server version |
|
|
609
|
+
| `doc://readme` | MAY | Mirror of the README |
|
|
610
|
+
|
|
611
|
+
### 11.3. Resource definition format
|
|
612
|
+
|
|
613
|
+
An item in `resources/list.result.resources[]` SHOULD describe:
|
|
614
|
+
|
|
615
|
+
| Field | Level | Purpose |
|
|
616
|
+
| ----- | ----- | ------- |
|
|
617
|
+
| `uri` | MUST | Unique resource URI |
|
|
618
|
+
| `name` | MUST | Resource name |
|
|
619
|
+
| `title` | MAY | Human-readable title for UI |
|
|
620
|
+
| `description` | MAY | Description |
|
|
621
|
+
| `mimeType` | MAY | MIME type |
|
|
622
|
+
| `size` | MAY | Size in bytes |
|
|
623
|
+
| `icons` | MAY | Icons for UI |
|
|
624
|
+
|
|
625
|
+
### 11.4. `resources/read` format
|
|
626
|
+
|
|
627
|
+
`resources/read` MUST return content inside `result.contents[]`. Each content item MUST contain `uri`,
|
|
628
|
+
`mimeType`, and one of the fields `text` or `blob`.
|
|
629
|
+
|
|
630
|
+
Example:
|
|
631
|
+
|
|
632
|
+
```json
|
|
633
|
+
{
|
|
634
|
+
"jsonrpc": "2.0",
|
|
635
|
+
"id": 2,
|
|
636
|
+
"result": {
|
|
637
|
+
"contents": [
|
|
638
|
+
{
|
|
639
|
+
"uri": "doc://readme",
|
|
640
|
+
"mimeType": "text/markdown",
|
|
641
|
+
"text": "# README"
|
|
642
|
+
}
|
|
643
|
+
]
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
### 11.5. Additional resource capabilities
|
|
649
|
+
|
|
650
|
+
The server MAY support resource templates:
|
|
651
|
+
|
|
652
|
+
- declare the `resources` capability;
|
|
653
|
+
- implement `resources/templates/list`;
|
|
654
|
+
- return `resourceTemplates[]` with `uriTemplate`, `name`, `title`, `description`, `mimeType`, `icons`.
|
|
655
|
+
|
|
656
|
+
The server MAY support subscriptions:
|
|
657
|
+
|
|
658
|
+
- declare `resources.subscribe=true`;
|
|
659
|
+
- accept `resources/subscribe`;
|
|
660
|
+
- send `notifications/resources/updated` when a resource changes;
|
|
661
|
+
- send `notifications/resources/list_changed` if `resources.listChanged=true` is declared.
|
|
662
|
+
|
|
663
|
+
## 12. Result format
|
|
664
|
+
|
|
665
|
+
### 12.1. Allowed tool result formats
|
|
666
|
+
|
|
667
|
+
A tool result MAY contain one or both formats:
|
|
668
|
+
|
|
669
|
+
| Format | When to use |
|
|
670
|
+
| ------------------- | ------------------------------------------- |
|
|
671
|
+
| `content` | Human-readable responses, markdown, text, image/audio/resource content |
|
|
672
|
+
| `structuredContent` | Machine-readable JSON data with a fixed schema |
|
|
673
|
+
|
|
674
|
+
For a specific tool, the format must be deterministic and documented.
|
|
675
|
+
|
|
676
|
+
### 12.2. Requirements
|
|
677
|
+
|
|
678
|
+
- if the response is truncated by limits, the truncation flag MUST be visible to the client (as text in
|
|
679
|
+
`content` or a field in `structuredContent`);
|
|
680
|
+
- personal / sensitive data MUST be protected per the domain policy (masking, filtering);
|
|
681
|
+
- binary data is transmitted as `blob` with the correct `mimeType`;
|
|
682
|
+
- if `structuredContent` and `outputSchema` are used, the result MUST conform to `outputSchema`;
|
|
683
|
+
- for backward compatibility, `structuredContent` SHOULD be duplicated in `content` as serialized JSON
|
|
684
|
+
text.
|
|
685
|
+
|
|
686
|
+
### 12.3. Text response example
|
|
687
|
+
|
|
688
|
+
```json
|
|
689
|
+
{
|
|
690
|
+
"content": [
|
|
691
|
+
{ "type": "text", "text": "..." }
|
|
692
|
+
]
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
### 12.4. Structured response example
|
|
697
|
+
|
|
698
|
+
```json
|
|
699
|
+
{
|
|
700
|
+
"content": [
|
|
701
|
+
{ "type": "text", "text": "{\"rows\":[],\"truncated\":false,\"rowCount\":0}" }
|
|
702
|
+
],
|
|
703
|
+
"structuredContent": {
|
|
704
|
+
"rows": [],
|
|
705
|
+
"truncated": false,
|
|
706
|
+
"rowCount": 0
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
## 13. Error format
|
|
712
|
+
|
|
713
|
+
### 13.1. Protocol errors and tool execution errors
|
|
714
|
+
|
|
715
|
+
MCP uses two types of errors:
|
|
716
|
+
|
|
717
|
+
| Type | When to use | Format |
|
|
718
|
+
| ---- | ----------- | ------ |
|
|
719
|
+
| Protocol error | Invalid JSON-RPC, unknown method, malformed params, transport/protocol layer error | JSON-RPC error object |
|
|
720
|
+
| Tool execution error | The tool was called correctly, but the domain operation failed or the input can be fixed | `result.isError=true` |
|
|
721
|
+
|
|
722
|
+
Protocol error example:
|
|
723
|
+
|
|
724
|
+
```json
|
|
725
|
+
{
|
|
726
|
+
"jsonrpc": "2.0",
|
|
727
|
+
"id": "<request-id>",
|
|
728
|
+
"error": {
|
|
729
|
+
"code": -32602,
|
|
730
|
+
"message": "Invalid params",
|
|
731
|
+
"data": { "field": "name", "reason": "required" }
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### 13.2. Classes of protocol errors
|
|
737
|
+
|
|
738
|
+
The full list is in [Appendix B](#appendix-b-error-codes).
|
|
739
|
+
|
|
740
|
+
| Class | JSON-RPC code | HTTP |
|
|
741
|
+
| -------------------- | ----------------- | ------ |
|
|
742
|
+
| Parse error | -32700 | 400 |
|
|
743
|
+
| Invalid request | -32600 | 400 |
|
|
744
|
+
| Method not found | -32601 | 404 |
|
|
745
|
+
| Invalid params | -32602 | 400 |
|
|
746
|
+
| Internal error | -32603 | 500 |
|
|
747
|
+
| Server error | -32000 | 500 |
|
|
748
|
+
| Resource not found | -32002 | 404 |
|
|
749
|
+
| Rate limited | -32003 | 429 |
|
|
750
|
+
| Timeout | -32004 | 504 |
|
|
751
|
+
| Payload too large | -32005 | 413 |
|
|
752
|
+
| Upstream unavailable | -32006 | 503 |
|
|
753
|
+
| Conflict | -32007 | 409 |
|
|
754
|
+
|
|
755
|
+
Auth failures at the HTTP layer are returned via HTTP 401/403 and `WWW-Authenticate`, not by overriding the
|
|
756
|
+
standard JSON-RPC codes.
|
|
757
|
+
|
|
758
|
+
### 13.3. Prohibitions
|
|
759
|
+
|
|
760
|
+
An error returned externally MUST NOT contain:
|
|
761
|
+
|
|
762
|
+
- a stack trace;
|
|
763
|
+
- secrets, tokens, passwords, connection strings;
|
|
764
|
+
- internal filesystem paths;
|
|
765
|
+
- raw SQL/expression text with user data;
|
|
766
|
+
- internal service names that are not part of the public contract.
|
|
767
|
+
|
|
768
|
+
## 14. Limits and protection
|
|
769
|
+
|
|
770
|
+
Each server MUST document and enforce:
|
|
771
|
+
|
|
772
|
+
| Limit | Default | Level |
|
|
773
|
+
| --------------------------- | ------------- | ----- |
|
|
774
|
+
| Input payload size | 1 MB | MUST |
|
|
775
|
+
| Tool result size | 10 MB | MUST |
|
|
776
|
+
| Tool call timeout | 30 seconds | MUST |
|
|
777
|
+
| Rate limit per token | service-defined | SHOULD |
|
|
778
|
+
| Max concurrent calls per token | service-defined | SHOULD |
|
|
779
|
+
|
|
780
|
+
On exceeding a limit:
|
|
781
|
+
|
|
782
|
+
- payload too large → `-32005` / HTTP 413;
|
|
783
|
+
- result too large → truncation with an explicit flag;
|
|
784
|
+
- timeout → `-32004` / HTTP 504;
|
|
785
|
+
- rate limit → `-32003` / HTTP 429 with the `Retry-After` header.
|
|
786
|
+
|
|
787
|
+
On timeout, the sender SHOULD send `notifications/cancelled` and stop waiting for the response if applicable
|
|
788
|
+
to the current transport/session.
|
|
789
|
+
|
|
790
|
+
## 15. Observability
|
|
791
|
+
|
|
792
|
+
### 15.1. Correlation
|
|
793
|
+
|
|
794
|
+
For servers with the HTTP / Streamable HTTP transport, the server MUST support propagating identifiers via
|
|
795
|
+
HTTP headers:
|
|
796
|
+
|
|
797
|
+
| Header | Level | Behavior |
|
|
798
|
+
| ---------------- | ----- | ------------------------------------------ |
|
|
799
|
+
| `X-Request-Id` | MUST | Accept; generate if absent; return in the response |
|
|
800
|
+
| `traceparent` | SHOULD | Accept the W3C trace context |
|
|
801
|
+
| `tracestate` | MAY | Propagate further |
|
|
802
|
+
| `MCP-Session-Id` | MAY | Use to correlate MCP session events, but not as identity |
|
|
803
|
+
|
|
804
|
+
For the stdio transport, the server MUST generate its own request id per JSON-RPC call and use it in logs
|
|
805
|
+
for correlation.
|
|
806
|
+
|
|
807
|
+
### 15.2. Logging
|
|
808
|
+
|
|
809
|
+
The server MUST log:
|
|
810
|
+
|
|
811
|
+
- the fact of a tool call: name, request id, duration, status (ok / error class);
|
|
812
|
+
- auth-failure facts: reason, request id;
|
|
813
|
+
- internal errors with full context — **only to internal logs**, never externally.
|
|
814
|
+
|
|
815
|
+
The server MUST NOT log:
|
|
816
|
+
|
|
817
|
+
- `arguments` values containing personal data, without masking;
|
|
818
|
+
- tokens, passwords, `Authorization` headers.
|
|
819
|
+
|
|
820
|
+
### 15.3. Metrics
|
|
821
|
+
|
|
822
|
+
SHOULD expose:
|
|
823
|
+
|
|
824
|
+
- a call counter by tool and status;
|
|
825
|
+
- a call-duration histogram;
|
|
826
|
+
- an auth-failures counter;
|
|
827
|
+
- a rate-limit events counter.
|
|
828
|
+
|
|
829
|
+
## 16. Health and readiness
|
|
830
|
+
|
|
831
|
+
### 16.1. `/health` (liveness)
|
|
832
|
+
|
|
833
|
+
| Property | Requirement |
|
|
834
|
+
| ----------------- | ----------------------------------- |
|
|
835
|
+
| Method | GET |
|
|
836
|
+
| Authentication | NOT required |
|
|
837
|
+
| Body | JSON |
|
|
838
|
+
| HTTP 200 | service is alive |
|
|
839
|
+
| HTTP 503 | service cannot serve requests |
|
|
840
|
+
|
|
841
|
+
Minimal body:
|
|
842
|
+
|
|
843
|
+
```json
|
|
844
|
+
{
|
|
845
|
+
"status": "ok",
|
|
846
|
+
"version": "1.2.3",
|
|
847
|
+
"uptime": 3600
|
|
848
|
+
}
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
### 16.2. `/ready` (readiness)
|
|
852
|
+
|
|
853
|
+
SHOULD. Returns 200 only when the server is ready to accept `tools/call` (including dependency readiness:
|
|
854
|
+
DB, secret store, JWKS).
|
|
855
|
+
|
|
856
|
+
```json
|
|
857
|
+
{
|
|
858
|
+
"status": "ready",
|
|
859
|
+
"checks": {
|
|
860
|
+
"db": "ok",
|
|
861
|
+
"jwks": "ok"
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### 16.3. Prohibitions
|
|
867
|
+
|
|
868
|
+
The `/health` and `/ready` responses MUST NOT include:
|
|
869
|
+
|
|
870
|
+
- secrets;
|
|
871
|
+
- connection strings;
|
|
872
|
+
- full dependency error messages (status only).
|
|
873
|
+
|
|
874
|
+
## 17. Contract stability and deprecation
|
|
875
|
+
|
|
876
|
+
### 17.1. What is part of the public contract
|
|
877
|
+
|
|
878
|
+
| Element | Stability |
|
|
879
|
+
| -------------------------------- | ------------- |
|
|
880
|
+
| Supported transports | MAJOR |
|
|
881
|
+
| HTTP endpoints (`/mcp`, `/health`, legacy `/sse`) | MAJOR |
|
|
882
|
+
| Authentication scheme | MAJOR |
|
|
883
|
+
| List of tools (names) | MAJOR |
|
|
884
|
+
| Tool `inputSchema` (required fields) | MAJOR |
|
|
885
|
+
| Tool `outputSchema` | MAJOR if published |
|
|
886
|
+
| Result format of each tool | MAJOR |
|
|
887
|
+
| Prompt names | MAJOR |
|
|
888
|
+
| URI scheme and base resources | MAJOR |
|
|
889
|
+
| Error codes | MAJOR |
|
|
890
|
+
| Adding a new tool / prompt / resource | MINOR |
|
|
891
|
+
| Adding an optional field | MINOR |
|
|
892
|
+
| Extending a `description` | PATCH |
|
|
893
|
+
|
|
894
|
+
### 17.2. Deprecation process
|
|
895
|
+
|
|
896
|
+
1. The `description` of the tool/prompt/resource gets a `[DEPRECATED]` prefix and a support deadline.
|
|
897
|
+
2. It is announced in the server's CHANGELOG.
|
|
898
|
+
3. The minimum period before removal is **2 MINOR versions** or **3 months**, whichever is longer.
|
|
899
|
+
4. Known consumers are notified (via the owner team).
|
|
900
|
+
5. After the deadline, removal happens in the next MAJOR.
|
|
901
|
+
|
|
902
|
+
### 17.3. CHANGELOG
|
|
903
|
+
|
|
904
|
+
The server MUST maintain a `CHANGELOG.md` in the Keep a Changelog format.
|
|
905
|
+
|
|
906
|
+
## 18. Compliance checklist
|
|
907
|
+
|
|
908
|
+
Minimal acceptance checklist. All MUST items are mandatory to pass review.
|
|
909
|
+
|
|
910
|
+
### Transport and HTTP
|
|
911
|
+
|
|
912
|
+
- [ ] at least one transport from {stdio, streamable_http, legacy_http_sse} is supported
|
|
913
|
+
- [ ] for Streamable HTTP, `POST /mcp` is implemented
|
|
914
|
+
- [ ] `POST /mcp` accepts `Accept: application/json, text/event-stream`
|
|
915
|
+
- [ ] `MCP-Protocol-Version` is supported after initialization
|
|
916
|
+
- [ ] if sessions are used, `MCP-Session-Id` is supported
|
|
917
|
+
- [ ] `GET /health` is implemented for HTTP
|
|
918
|
+
- [ ] CORS is configured explicitly, without `*` in production
|
|
919
|
+
- [ ] `Origin` is validated; an invalid origin returns 403
|
|
920
|
+
- [ ] the maximum payload size is documented
|
|
921
|
+
|
|
922
|
+
### Authentication
|
|
923
|
+
|
|
924
|
+
- [ ] HTTP / Streamable HTTP requires authentication on `tools/call`
|
|
925
|
+
- [ ] `Authorization: Bearer <token>` is supported
|
|
926
|
+
- [ ] JWT is validated by issuer / audience / exp (see Appendix A)
|
|
927
|
+
- [ ] 401 contains a correct `WWW-Authenticate`
|
|
928
|
+
- [ ] for generic MCP clients, OAuth discovery is described, or the server is explicitly marked internal-only
|
|
929
|
+
- [ ] token passthrough is forbidden
|
|
930
|
+
- [ ] secrets are not passed in the query / logs
|
|
931
|
+
|
|
932
|
+
### MCP lifecycle and methods
|
|
933
|
+
|
|
934
|
+
- [ ] `initialize` responds with the protocol version, capabilities, and `serverInfo`
|
|
935
|
+
- [ ] the server accepts `notifications/initialized`
|
|
936
|
+
- [ ] only negotiated capabilities are used
|
|
937
|
+
- [ ] `tools/list` and `tools/call` work if the `tools` capability is declared
|
|
938
|
+
- [ ] `prompts/list` and `prompts/get` work if the `prompts` capability is declared
|
|
939
|
+
- [ ] `resources/list` and `resources/read` work if the `resources` capability is declared
|
|
940
|
+
- [ ] an unknown method → `-32601`
|
|
941
|
+
|
|
942
|
+
### Tools
|
|
943
|
+
|
|
944
|
+
- [ ] all tools have `name`, `description`, `inputSchema`
|
|
945
|
+
- [ ] names are snake_case and English
|
|
946
|
+
- [ ] `inputSchema` is compatible with JSON Schema 2020-12 or explicitly specifies `$schema`
|
|
947
|
+
- [ ] `arguments` are validated against the schema
|
|
948
|
+
- [ ] mutating tools state their side effects and risk level
|
|
949
|
+
- [ ] tools with external side effects document idempotency, retry, timeout, audit, and approval
|
|
950
|
+
- [ ] business/tool execution errors are returned via `result.isError=true`
|
|
951
|
+
- [ ] the result format is deterministic
|
|
952
|
+
|
|
953
|
+
### Prompts
|
|
954
|
+
|
|
955
|
+
- [ ] prompts are declared only if the `prompts` capability exists
|
|
956
|
+
- [ ] if the server participates in agent routing, `agent_brief` and `agent_prompt` are published, or the deviation is explained in the README
|
|
957
|
+
- [ ] prompt arguments are described via the standard MCP `arguments[]`, not as an `inputSchema`
|
|
958
|
+
|
|
959
|
+
### Resources
|
|
960
|
+
|
|
961
|
+
- [ ] if there are non-standard headers, `use://http-headers` is published
|
|
962
|
+
- [ ] URIs use scheme = service name or the corporate schemes `use://`, `project://`, `doc://`
|
|
963
|
+
- [ ] `resources/read` returns `result.contents[]` with `uri`, `mimeType`, `text` or `blob`
|
|
964
|
+
- [ ] `resources/templates/list` and subscriptions are implemented only if the corresponding capabilities are declared
|
|
965
|
+
|
|
966
|
+
### Errors and limits
|
|
967
|
+
|
|
968
|
+
- [ ] protocol errors are returned in the JSON-RPC format
|
|
969
|
+
- [ ] tool execution errors are returned via `isError=true`
|
|
970
|
+
- [ ] error codes match Appendix B
|
|
971
|
+
- [ ] timeout, rate limit, payload limit are implemented and documented
|
|
972
|
+
- [ ] errors do not contain a stacktrace or secrets
|
|
973
|
+
|
|
974
|
+
### Observability
|
|
975
|
+
|
|
976
|
+
- [ ] `X-Request-Id` is supported
|
|
977
|
+
- [ ] `traceparent` is accepted if the W3C trace context is used
|
|
978
|
+
- [ ] there is structured logging of calls
|
|
979
|
+
- [ ] logs do not contain tokens and PII without masking
|
|
980
|
+
|
|
981
|
+
### Documentation and contract
|
|
982
|
+
|
|
983
|
+
- [ ] there is a README describing the public contract
|
|
984
|
+
- [ ] there is a CHANGELOG.md
|
|
985
|
+
- [ ] semver is followed
|
|
986
|
+
- [ ] the version is available in `/health` and `initialize.result.serverInfo.version`
|
|
987
|
+
- [ ] the `project://version` resource is implemented, or it is explicitly acknowledged as optional for the server
|
|
988
|
+
|
|
989
|
+
---
|
|
990
|
+
|
|
991
|
+
## Appendix A. Auth profile
|
|
992
|
+
|
|
993
|
+
### A.1. JWT — the mandatory profile for internal servers
|
|
994
|
+
|
|
995
|
+
| Parameter | Requirement |
|
|
996
|
+
| ----------------- | ------------------------------------------------ |
|
|
997
|
+
| Signing algorithm | RS256 or ES256 (HS256 — local development only) |
|
|
998
|
+
| Key source | Corporate JWKS endpoint |
|
|
999
|
+
| JWKS cache | TTL ≤ 10 minutes |
|
|
1000
|
+
| `exp` validation | MUST |
|
|
1001
|
+
| `nbf` validation | MUST if present |
|
|
1002
|
+
| `iss` validation | MUST, value from config |
|
|
1003
|
+
| `aud` validation | MUST, value = server identifier |
|
|
1004
|
+
| Allowed clock skew | ≤ 60 seconds |
|
|
1005
|
+
|
|
1006
|
+
### A.2. Minimal set of claims
|
|
1007
|
+
|
|
1008
|
+
| Claim | Type | Purpose |
|
|
1009
|
+
| ------- | ------ | --------------------------------------- |
|
|
1010
|
+
| `iss` | string | Issuer (corporate IdP) |
|
|
1011
|
+
| `aud` | string | Target server identifier |
|
|
1012
|
+
| `sub` | string | Subject identifier (user / service) |
|
|
1013
|
+
| `exp` | number | Expiration |
|
|
1014
|
+
| `iat` | number | Issued-at time |
|
|
1015
|
+
| `scope` | string | Space-separated list of scopes (if used) |
|
|
1016
|
+
|
|
1017
|
+
### A.3. Opaque tokens
|
|
1018
|
+
|
|
1019
|
+
Allowed only if:
|
|
1020
|
+
|
|
1021
|
+
- stored in the corporate secret store;
|
|
1022
|
+
- rotated per company policy;
|
|
1023
|
+
- verified via an introspection endpoint or a built-in whitelist.
|
|
1024
|
+
|
|
1025
|
+
### A.4. Basic Auth
|
|
1026
|
+
|
|
1027
|
+
- HTTPS only;
|
|
1028
|
+
- admin/service endpoints only;
|
|
1029
|
+
- credentials taken from the secret store, not from code.
|
|
1030
|
+
|
|
1031
|
+
### A.5. Header examples
|
|
1032
|
+
|
|
1033
|
+
```http
|
|
1034
|
+
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
1035
|
+
MCP-Protocol-Version: 2025-11-25
|
|
1036
|
+
MCP-Session-Id: 1868a90c-7c1e-4f8c-9c19-2d28d9e4f1aa
|
|
1037
|
+
Accept: application/json, text/event-stream
|
|
1038
|
+
X-Request-Id: 6f1c4f0e-2b7a-4f3e-8b7e-1a9b5c2d3e4f
|
|
1039
|
+
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
---
|
|
1043
|
+
|
|
1044
|
+
## Appendix B. Error codes
|
|
1045
|
+
|
|
1046
|
+
### B.1. JSON-RPC codes
|
|
1047
|
+
|
|
1048
|
+
| Code | Name | HTTP | When |
|
|
1049
|
+
| -------- | ------------------ | ---- | ------------------------------------------- |
|
|
1050
|
+
| -32700 | Parse error | 400 | Invalid JSON |
|
|
1051
|
+
| -32600 | Invalid Request | 400 | Does not conform to JSON-RPC |
|
|
1052
|
+
| -32601 | Method not found | 404 | Unknown MCP method |
|
|
1053
|
+
| -32602 | Invalid params | 400 | Invalid params structure / unknown tool name |
|
|
1054
|
+
| -32603 | Internal error | 500 | Internal error of the JSON-RPC layer |
|
|
1055
|
+
|
|
1056
|
+
### B.2. Server codes (range -32000…-32099)
|
|
1057
|
+
|
|
1058
|
+
| Code | Name | HTTP | When |
|
|
1059
|
+
| -------- | ------------------ | ---- | ------------------------------------------- |
|
|
1060
|
+
| -32000 | Server error | 500 | Internal server error not related to tool execution |
|
|
1061
|
+
| -32002 | Resource not found | 404 | Resource not found |
|
|
1062
|
+
| -32003 | Rate limited | 429 | Rate limit exceeded; include `Retry-After` |
|
|
1063
|
+
| -32004 | Timeout | 504 | Call timeout exceeded |
|
|
1064
|
+
| -32005 | Payload too large | 413 | Size limit exceeded |
|
|
1065
|
+
| -32006 | Upstream unavailable | 503 | A dependency is unavailable (DB, etc.) |
|
|
1066
|
+
| -32007 | Conflict | 409 | State conflict (if applicable) |
|
|
1067
|
+
|
|
1068
|
+
Auth failures are returned via HTTP 401/403. For insufficient scope/resource access, the server SHOULD use
|
|
1069
|
+
HTTP 403 at the transport layer; if the error relates to a specific resource inside MCP, use a safe
|
|
1070
|
+
protocol error or a tool/resource-specific response without disclosing secrets.
|
|
1071
|
+
|
|
1072
|
+
### B.3. `error.data` structure
|
|
1073
|
+
|
|
1074
|
+
`error.data` SHOULD contain the fields:
|
|
1075
|
+
|
|
1076
|
+
| Field | Type | Purpose |
|
|
1077
|
+
| ---------- | ------ | ------------------------------------------- |
|
|
1078
|
+
| `requestId`| string | Request correlation id |
|
|
1079
|
+
| `field` | string | Field name for validation errors |
|
|
1080
|
+
| `reason` | string | Machine-readable reason (`required`, `format`, `range`, etc.) |
|
|
1081
|
+
| `retryAfter` | number | Seconds until retry (for -32003) |
|
|
1082
|
+
|
|
1083
|
+
### B.4. Forbidden content
|
|
1084
|
+
|
|
1085
|
+
In `message` and `data`, the following is FORBIDDEN:
|
|
1086
|
+
|
|
1087
|
+
- stack traces;
|
|
1088
|
+
- internal paths;
|
|
1089
|
+
- secrets of any kind;
|
|
1090
|
+
- raw user input text with potential PII.
|
|
1091
|
+
|
|
1092
|
+
---
|
|
1093
|
+
|
|
1094
|
+
## Appendix C. Input / output summary table
|
|
1095
|
+
|
|
1096
|
+
### C.1. What the server accepts
|
|
1097
|
+
|
|
1098
|
+
| Source | What | Level |
|
|
1099
|
+
| ----------------------- | ------------------------------------ | ------- |
|
|
1100
|
+
| Transport | stdio / streamable_http / legacy_http_sse | at least one MUST |
|
|
1101
|
+
| HTTP | `POST /mcp`, `GET /health` | MUST for a streamable_http server |
|
|
1102
|
+
| HTTP | `GET /mcp` | MAY for the SSE stream |
|
|
1103
|
+
| HTTP | `GET /sse` | MAY, legacy only |
|
|
1104
|
+
| Header | `Authorization: Bearer <token>` | MUST for HTTP / Streamable HTTP |
|
|
1105
|
+
| Header | `MCP-Protocol-Version` | MUST after `initialize` for HTTP |
|
|
1106
|
+
| Header | `MCP-Session-Id` | MUST if the server issued a session id |
|
|
1107
|
+
| Header | `Accept: application/json, text/event-stream` | MUST for `POST /mcp` |
|
|
1108
|
+
| Header | `X-Request-Id` | MUST accept |
|
|
1109
|
+
| Header | `traceparent` | SHOULD |
|
|
1110
|
+
| MCP method | `initialize` | MUST |
|
|
1111
|
+
| MCP notification | `notifications/initialized` | MUST accept |
|
|
1112
|
+
| MCP method | `tools/list`, `tools/call` | MUST if the `tools` capability exists |
|
|
1113
|
+
| MCP method | `prompts/list`, `prompts/get` | MUST if the `prompts` capability exists |
|
|
1114
|
+
| MCP method | `resources/list`, `resources/read` | MUST if the `resources` capability exists |
|
|
1115
|
+
| MCP method | `resources/templates/list` | MAY |
|
|
1116
|
+
| MCP method | `resources/subscribe` | MAY |
|
|
1117
|
+
| MCP notification | `notifications/cancelled` | SHOULD for long-running operations |
|
|
1118
|
+
| `tools/call.params` | `name`, `arguments` | MUST |
|
|
1119
|
+
| `prompts/get.params` | `name`, `arguments?` | MUST |
|
|
1120
|
+
| `resources/read.params` | `uri` | MUST |
|
|
1121
|
+
|
|
1122
|
+
### C.2. What the server returns
|
|
1123
|
+
|
|
1124
|
+
| Where | What | Level |
|
|
1125
|
+
| ----------------------- | ------------------------------------ | ------- |
|
|
1126
|
+
| `initialize.result` | `protocolVersion`, `capabilities`, `serverInfo` | MUST |
|
|
1127
|
+
| `tools/list.result` | tools with `name`, `description`, `inputSchema`; SHOULD `title`, MAY `icons`, `outputSchema`, `execution` | MUST if tools exist |
|
|
1128
|
+
| `tools/call.result` | `content`, `structuredContent`, `isError?` | MUST if tools exist |
|
|
1129
|
+
| `prompts/list.result` | prompts; `agent_brief` / `agent_prompt` SHOULD for Avatar routing | MUST if prompts exist |
|
|
1130
|
+
| `prompts/get.result` | `description?`, `messages[]` | MUST if prompts exist |
|
|
1131
|
+
| `resources/list.result` | list of resources with `uri`, `name`, optional `title`, `mimeType`, `icons` | MUST if resources exist |
|
|
1132
|
+
| `resources/read.result` | `contents[]` with `uri`, `mimeType`, `text` or `blob` | MUST if resources exist |
|
|
1133
|
+
| `GET /health` | JSON with `status`, `version`, `uptime` | MUST for HTTP |
|
|
1134
|
+
| `GET /ready` | JSON with `status`, `checks` | SHOULD |
|
|
1135
|
+
| Response header | `X-Request-Id` | MUST |
|
|
1136
|
+
| Response header | `MCP-Session-Id` | MAY on `initialize` |
|
|
1137
|
+
| Response header (401) | `WWW-Authenticate: Bearer ...` or an OAuth resource metadata challenge | MUST |
|
|
1138
|
+
| Response header (429) | `Retry-After` | MUST |
|
|
1139
|
+
| Protocol error | JSON-RPC error object without secrets and stacktraces | MUST |
|
|
1140
|
+
| Tool execution error | `result.isError=true` | MUST for tool domain errors |
|
|
1141
|
+
|
|
1142
|
+
### C.3. What the server MUST NOT return externally
|
|
1143
|
+
|
|
1144
|
+
- stack traces;
|
|
1145
|
+
- secrets, tokens, passwords, connection strings;
|
|
1146
|
+
- internal paths and service names;
|
|
1147
|
+
- raw SQL / DSL queries with user data;
|
|
1148
|
+
- personal data beyond what the domain allows.
|